|
|
@@ -121,7 +121,7 @@ this.htmlmini = this.htmlmini || (() => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- const modules = [collapseBooleanAttributes, mergeTextNodes, collapseWhitespace, removeComments, removeEmptyAttributes, removeRedundantAttributes];
|
|
|
+ const modules = [collapseBooleanAttributes, mergeTextNodes, collapseWhitespace, removeComments, removeEmptyAttributes, removeRedundantAttributes, node => mergeElements(node, "STYLE", (node, previousSibling) => node.media == previousSibling.media)];
|
|
|
|
|
|
return {
|
|
|
process: (doc, options) => {
|
|
|
@@ -160,6 +160,22 @@ this.htmlmini = this.htmlmini || (() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ function mergeElements(node, tagName, testFn) {
|
|
|
+ if (node.nodeType == Node.ELEMENT_NODE && node.tagName == tagName) {
|
|
|
+ let previousSibling = node.previousSibling;
|
|
|
+ let previousSiblings = [];
|
|
|
+ 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 && testFn(node, previousSibling)) {
|
|
|
+ node.textContent = previousSibling.textContent + node.textContent;
|
|
|
+ previousSiblings.forEach(node => node.remove());
|
|
|
+ previousSibling.remove();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
function collapseWhitespace(node, options) {
|
|
|
if (node.nodeType == Node.TEXT_NODE) {
|
|
|
let element = node.parentElement;
|
|
|
@@ -174,7 +190,7 @@ this.htmlmini = this.htmlmini || (() => {
|
|
|
let lastTextContent;
|
|
|
while (lastTextContent != textContent) {
|
|
|
lastTextContent = textContent;
|
|
|
- textContent = textContent.replace(/[ \n\t\f\r]+/g, " ");
|
|
|
+ textContent = textContent.replace(/[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+/g, " ");
|
|
|
}
|
|
|
node.textContent = textContent;
|
|
|
}
|