|
|
@@ -25,8 +25,6 @@
|
|
|
|
|
|
// Derived from the work of Kirill Maltsev - https://github.com/posthtml/htmlnano
|
|
|
|
|
|
-/* global Node, NodeFilter */
|
|
|
-
|
|
|
this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
|
|
|
// Source: https://github.com/kangax/html-minifier/issues/63
|
|
|
@@ -121,6 +119,10 @@ this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
const REGEXP_WHITESPACE = /[ \t\f\r]+/g;
|
|
|
const REGEXP_NEWLINE = /[\n]+/g;
|
|
|
const REGEXP_ENDS_WHITESPACE = /^\s+$/;
|
|
|
+ const NodeFilter_SHOW_ALL = 4294967295;
|
|
|
+ const Node_ELEMENT_NODE = 1;
|
|
|
+ const Node_TEXT_NODE = 3;
|
|
|
+ const Node_COMMENT_NODE = 8;
|
|
|
|
|
|
const modules = [
|
|
|
collapseBooleanAttributes,
|
|
|
@@ -136,7 +138,7 @@ this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
return {
|
|
|
process: (doc, options) => {
|
|
|
removeEmptyInlineElements(doc);
|
|
|
- const nodesWalker = doc.createTreeWalker(doc.documentElement, NodeFilter.SHOW_ALL, null, false);
|
|
|
+ const nodesWalker = doc.createTreeWalker(doc.documentElement, NodeFilter_SHOW_ALL, null, false);
|
|
|
let node = nodesWalker.nextNode();
|
|
|
while (node) {
|
|
|
const deletedNode = modules.find(module => module(node, options));
|
|
|
@@ -150,7 +152,7 @@ this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
};
|
|
|
|
|
|
function collapseBooleanAttributes(node) {
|
|
|
- if (node.nodeType == Node.ELEMENT_NODE) {
|
|
|
+ if (node.nodeType == Node_ELEMENT_NODE) {
|
|
|
Array.from(node.attributes).forEach(attribute => {
|
|
|
if (booleanAttributes.includes(attribute.name)) {
|
|
|
node.setAttribute(attribute.name, "");
|
|
|
@@ -160,8 +162,8 @@ this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
}
|
|
|
|
|
|
function mergeTextNodes(node) {
|
|
|
- if (node.nodeType == Node.TEXT_NODE) {
|
|
|
- if (node.previousSibling && node.previousSibling.nodeType == Node.TEXT_NODE) {
|
|
|
+ if (node.nodeType == Node_TEXT_NODE) {
|
|
|
+ if (node.previousSibling && node.previousSibling.nodeType == Node_TEXT_NODE) {
|
|
|
node.textContent = node.previousSibling.textContent + node.textContent;
|
|
|
node.previousSibling.remove();
|
|
|
}
|
|
|
@@ -169,14 +171,14 @@ this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
}
|
|
|
|
|
|
function mergeElements(node, tagName, acceptMerge) {
|
|
|
- if (node.nodeType == Node.ELEMENT_NODE && node.tagName.toLowerCase() == tagName.toLowerCase()) {
|
|
|
+ if (node.nodeType == Node_ELEMENT_NODE && node.tagName.toLowerCase() == tagName.toLowerCase()) {
|
|
|
let previousSibling = node.previousSibling;
|
|
|
const previousSiblings = [];
|
|
|
- while (previousSibling && previousSibling.nodeType == Node.TEXT_NODE && !previousSibling.textContent.trim()) {
|
|
|
+ while (previousSibling && previousSibling.nodeType == Node_TEXT_NODE && !previousSibling.textContent.trim()) {
|
|
|
previousSiblings.push(previousSibling);
|
|
|
previousSibling = previousSibling.previousSibling;
|
|
|
}
|
|
|
- if (previousSibling && previousSibling.nodeType == Node.ELEMENT_NODE && previousSibling.tagName == node.tagName && acceptMerge(node, previousSibling)) {
|
|
|
+ if (previousSibling && previousSibling.nodeType == Node_ELEMENT_NODE && previousSibling.tagName == node.tagName && acceptMerge(node, previousSibling)) {
|
|
|
node.textContent = previousSibling.textContent + node.textContent;
|
|
|
previousSiblings.forEach(node => node.remove());
|
|
|
previousSibling.remove();
|
|
|
@@ -185,7 +187,7 @@ this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
}
|
|
|
|
|
|
function collapseWhitespace(node, options) {
|
|
|
- if (node.nodeType == Node.TEXT_NODE) {
|
|
|
+ if (node.nodeType == Node_TEXT_NODE) {
|
|
|
let element = node.parentElement;
|
|
|
const spacePreserved = element.getAttribute(options.preservedSpaceAttributeName) == "";
|
|
|
const textContent = node.textContent;
|
|
|
@@ -209,13 +211,13 @@ this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
}
|
|
|
|
|
|
function removeComments(node) {
|
|
|
- if (node.nodeType == Node.COMMENT_NODE) {
|
|
|
+ if (node.nodeType == Node_COMMENT_NODE) {
|
|
|
return !node.textContent.toLowerCase().trim().startsWith("[if");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function removeEmptyAttributes(node) {
|
|
|
- if (node.nodeType == Node.ELEMENT_NODE) {
|
|
|
+ if (node.nodeType == Node_ELEMENT_NODE) {
|
|
|
Array.from(node.attributes).forEach(attribute => {
|
|
|
if (safeToRemoveAttrs.includes(attribute.name.toLowerCase())) {
|
|
|
const attributeValue = node.getAttribute(attribute.name);
|
|
|
@@ -228,7 +230,7 @@ this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
}
|
|
|
|
|
|
function removeRedundantAttributes(node) {
|
|
|
- if (node.nodeType == Node.ELEMENT_NODE) {
|
|
|
+ if (node.nodeType == Node_ELEMENT_NODE) {
|
|
|
const tagRedundantAttributes = redundantAttributes[node.tagName.toLowerCase()];
|
|
|
if (tagRedundantAttributes) {
|
|
|
Object.keys(tagRedundantAttributes).forEach(redundantAttributeName => {
|
|
|
@@ -242,7 +244,7 @@ this.htmlMinifier = this.htmlMinifier || (() => {
|
|
|
}
|
|
|
|
|
|
function compressJSONLD(node) {
|
|
|
- if (node.nodeType == Node.ELEMENT_NODE && node.tagName == "SCRIPT" && node.type == "application/ld+json" && node.textContent.trim()) {
|
|
|
+ if (node.nodeType == Node_ELEMENT_NODE && node.tagName == "SCRIPT" && node.type == "application/ld+json" && node.textContent.trim()) {
|
|
|
try {
|
|
|
node.textContent = JSON.stringify(JSON.parse(node.textContent));
|
|
|
} catch (error) {
|