From 0aa4b05b1ec747f3f13e9e1c9c0fe710e264b538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Z=C3=B6rb?= Date: Fri, 20 Sep 2024 07:14:27 +0200 Subject: [PATCH 1/4] wip --- package-lock.json | 16 ++++++++-------- src/dom.js | 12 ++++++++++-- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9593224..ac20b82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7045,12 +7045,12 @@ "dev": true }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -14744,12 +14744,12 @@ "dev": true }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, diff --git a/src/dom.js b/src/dom.js index 6211b05..beb1039 100644 --- a/src/dom.js +++ b/src/dom.js @@ -94,6 +94,7 @@ class Dom { this.indent = detectIndent(html); this.headIndent = detectIndent(this.document.querySelector('head').innerHTML); + this.bodyIndent = detectIndent(this.document.querySelector('body').innerHTML); } serialize() { @@ -115,11 +116,18 @@ class Dom { : [...this.bodyElements]; if (head.length > 0) { - result = result.replaceAll(/^([\s\t]*)(<\/\s*head>)/gim, `$1$1${head.join('\n$1$1')}\n$1$2`); + const [, match] = /^([^\S\r\n]*)<\/\s*head>/gim.exec(html) || ['', null]; + const indent = match === null ? '' : `\n${match}`; + const headContent = `${indent}${this.headIndent.indent}${head.join(`${indent}${this.headIndent.indent}`)}`; + + result = result.replaceAll(`${indent}`, `${headContent}${indent}`); } if (body.length > 0) { - result = result.replaceAll(/^([\s\t]*)(<\/\s*body>)/gim, `$1$1${body.join('\n$1$1')}\n$1$2`); + const [, match] = /^([^\S\r\n]*)<\/\s*body>/gim.exec(html) || ['', null]; + const indent = match === null ? '' : `\n${match}`; + const bodyContent = `${indent}${this.bodyIndent.indent}${body.join(`${indent}${this.bodyIndent.indent}`)}`; + result = result.replaceAll(`${indent}`, `${bodyContent}${indent}`); } return result; From da72fb094c1befd6e7d217c8a1a948bc6ea64674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Z=C3=B6rb?= Date: Sun, 22 Sep 2024 22:58:29 +0200 Subject: [PATCH 2/4] Adds tests for minified html --- src/dom.js | 21 +++---- ...inlined-async-integrity-print-default.html | 6 +- test/helper/index.js | 2 +- test/index.test.js | 63 ++++++++++++++++--- 4 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/dom.js b/src/dom.js index beb1039..5da22a6 100644 --- a/src/dom.js +++ b/src/dom.js @@ -76,12 +76,10 @@ const replacePartials = (source, destination, tag) => { class Dom { constructor(html, {minify = true, noscript = 'body'} = {}) { - const jsdom = new JSDOM(html); - + const jsdom = new JSDOM(html.trim()); const {window} = jsdom; const {document} = window; document.$jsdom = jsdom; - this.noscriptPosition = noscript; this.minify = minify; this.html = html; @@ -116,18 +114,19 @@ class Dom { : [...this.bodyElements]; if (head.length > 0) { - const [, match] = /^([^\S\r\n]*)<\/\s*head>/gim.exec(html) || ['', null]; - const indent = match === null ? '' : `\n${match}`; - const headContent = `${indent}${this.headIndent.indent}${head.join(`${indent}${this.headIndent.indent}`)}`; + const [, match] = /^([^\S\r\n]*)<\/\s*head>/gim.exec(result) || ['', null]; + const nl = match === null ? '' : `\n`; + const headContent = `${this.indent.indent}${this.indent.indent}${head.join(`${nl}${this.indent.indent}${this.indent.indent}`)}`; - result = result.replaceAll(`${indent}`, `${headContent}${indent}`); + result = result.replaceAll(`${match || ''}`, `${headContent}${nl}${this.indent.indent}`); } if (body.length > 0) { - const [, match] = /^([^\S\r\n]*)<\/\s*body>/gim.exec(html) || ['', null]; - const indent = match === null ? '' : `\n${match}`; - const bodyContent = `${indent}${this.bodyIndent.indent}${body.join(`${indent}${this.bodyIndent.indent}`)}`; - result = result.replaceAll(`${indent}`, `${bodyContent}${indent}`); + const [, match] = /^([^\S\r\n]*)<\/\s*body>/gim.exec(result) || ['', null]; + const nl = match === null ? '' : `\n`; + const bodyContent = `${this.indent.indent}${this.indent.indent}${body.join(`${nl}${this.indent.indent}${this.indent.indent}`)}`; + + result = result.replaceAll(`${match || ''}`, `${bodyContent}${nl}${this.indent.indent}`); } return result; diff --git a/test/expected/index-inlined-async-integrity-print-default.html b/test/expected/index-inlined-async-integrity-print-default.html index aaa1cc9..b98f711 100644 --- a/test/expected/index-inlined-async-integrity-print-default.html +++ b/test/expected/index-inlined-async-integrity-print-default.html @@ -49,7 +49,7 @@

Bootstrap

♥ from the Yeoman team

- - - + + + diff --git a/test/helper/index.js b/test/helper/index.js index 84a31ec..df08231 100644 --- a/test/helper/index.js +++ b/test/helper/index.js @@ -26,7 +26,7 @@ export const checkAndDelete = (file) => { } }; -export const strip = (string) => nn(string.replaceAll(/[\r\n]+/gm, ' ').replaceAll(/\s+/gm, '')); +export const strip = (string, safe) => nn(string.replaceAll(/[\r\n]+/gm, ' ').replaceAll(/\s+/gm, safe ? ' ' : '')); export const getBinary = async () => { const {packageJson} = await readPackageUp(); diff --git a/test/index.test.js b/test/index.test.js index 078afba..2a07900 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -721,16 +721,6 @@ test('Keep existing integrity attribute on style tags with media=print', async ( expect(out.toString()).toBe(expected); }); -test('Keep existing integrity attribute on style tags with media=print', async () => { - const html = await read('fixtures/index-integrity.html'); - const css = await read('fixtures/critical.css'); - - const expected = await read('expected/index-inlined-async-integrity-print-default.html'); - const out = inline(html, css); - - expect(out.toString()).toBe(expected); -}); - test('Replace stylesheets (default)', async () => { const html = await read('fixtures/replace-stylesheets.html'); const css = await read('fixtures/css/simple.css'); @@ -808,6 +798,59 @@ test('Replace stylesheets (swap)', async () => { expect(out.toString()).toBe(expected); }); +test('Replace stylesheets (minified, polyfill)', async () => { + const html = await read('fixtures/replace-stylesheets.html'); + const css = await read('fixtures/css/simple.css'); + + const expected = await read('expected/replace-stylesheets-polyfill.html'); + const out = inline(strip(html, true), css, { + strategy: 'polyfill', + replaceStylesheets: ['/css/replaced.css'], + }); + + expect(strip(out.toString())).toBe(strip(expected)); +}); + +test('Replace stylesheets (minified, body)', async () => { + const html = await read('fixtures/replace-stylesheets.html'); + const css = await read('fixtures/css/simple.css'); + + const expected = await read('expected/replace-stylesheets-body.html'); + const out = inline(strip(html, true), css, { + strategy: 'body', + replaceStylesheets: ['/css/replaced.css'], + }); + + expect(strip(out.toString())).toBe(strip(expected)); +}); + +test('Replace stylesheets (minified, media)', async () => { + const html = await read('fixtures/replace-stylesheets.html'); + const css = await read('fixtures/css/simple.css'); + + const expected = await read('expected/replace-stylesheets-media.html'); + const out = inline(strip(html, true), css, { + strategy: 'media', + replaceStylesheets: ['/css/replaced.css'], + }); + + console.log('DEBUG:', strip(html, true)); + expect(strip(out.toString())).toBe(strip(expected)); +}); + +test('Replace stylesheets (minified, swap)', async () => { + const html = await read('fixtures/replace-stylesheets.html'); + const css = await read('fixtures/css/simple.css'); + + const expected = await read('expected/replace-stylesheets-swap.html'); + const out = inline(strip(html, true), css, { + strategy: 'swap', + replaceStylesheets: ['/css/replaced.css'], + }); + + expect(strip(out.toString())).toBe(strip(expected)); +}); + test('Issue 300', async () => { const html = await read('fixtures/issue-300.html'); const css = await read('fixtures/critical.css'); From f826233c438a0d2073b74833659519599c11dd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Z=C3=B6rb?= Date: Sun, 22 Sep 2024 23:01:52 +0200 Subject: [PATCH 3/4] Adds tests for minified html --- test/helper/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/helper/index.js b/test/helper/index.js index df08231..803f8c5 100644 --- a/test/helper/index.js +++ b/test/helper/index.js @@ -26,7 +26,8 @@ export const checkAndDelete = (file) => { } }; -export const strip = (string, safe) => nn(string.replaceAll(/[\r\n]+/gm, ' ').replaceAll(/\s+/gm, safe ? ' ' : '')); +export const strip = (string, safe) => + nn(string.replaceAll(/[\r\n]+/gm, ' ').replaceAll(/\s+/gm, safe ? ' ' : '')).replaceAll(/>\s+<'); export const getBinary = async () => { const {packageJson} = await readPackageUp(); From d64b90700f44006fd9eeb2d8af80c72abb878912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Z=C3=B6rb?= Date: Sun, 22 Sep 2024 23:06:23 +0200 Subject: [PATCH 4/4] cleanup --- src/dom.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/dom.js b/src/dom.js index 5da22a6..12c1b38 100644 --- a/src/dom.js +++ b/src/dom.js @@ -91,8 +91,6 @@ class Dom { this.bodyElements = []; this.indent = detectIndent(html); - this.headIndent = detectIndent(this.document.querySelector('head').innerHTML); - this.bodyIndent = detectIndent(this.document.querySelector('body').innerHTML); } serialize() { @@ -190,8 +188,8 @@ class Dom { appendStyles(css, referenceNode) { const styles = this.createStyleNode(css); referenceNode.append(styles); - styles.before(this.document.createTextNode(this.headIndent.indent)); - styles.after(this.document.createTextNode(`\n${this.headIndent.indent}`)); + styles.before(this.document.createTextNode(this.indent.indent)); + styles.after(this.document.createTextNode(`\n${this.indent.indent}`)); } addNoscript(link) {