diff --git a/__tests__/HtmlInlineScriptPlugin.test.ts b/__tests__/HtmlInlineScriptPlugin.test.ts index a518687..8306199 100644 --- a/__tests__/HtmlInlineScriptPlugin.test.ts +++ b/__tests__/HtmlInlineScriptPlugin.test.ts @@ -13,6 +13,7 @@ import ignoreScriptsConfig from './cases/ignore-scripts/webpack.config'; import ignoreHtmlsConfig from './cases/ignore-htmls/webpack.config'; import ignoreScriptsAndHtmlsConfig from './cases/ignore-scripts-and-htmls/webpack.config'; import filenameWithSpecialCharactersConfig from './cases/filename-with-special-characters/webpack.config'; +import escapeScriptTagEndConfig from './cases/escape-script-end-tag/webpack.config'; describe('HtmlInlineScriptPlugin', () => { it('should build simple webpack config without error', async () => { @@ -358,6 +359,38 @@ describe('HtmlInlineScriptPlugin', () => { await webpackPromise; }); + it('should escape any "" appears in source', async () => { + const webpackPromise = new Promise((resolve) => { + const compiler = webpack(escapeScriptTagEndConfig); + + compiler.run((error, stats) => { + expect(error).toBeNull(); + + const statsErrors = stats?.compilation.errors; + expect(statsErrors?.length).toBe(0); + + const result = fs.readFileSync( + path.join(__dirname, 'cases/escape-script-end-tag/dist/index.html'), + 'utf8', + ); + + const expected = fs.readFileSync( + path.join(__dirname, 'cases/escape-script-end-tag/expected/index.html'), + 'utf8', + ); + expect(result).toBe(expected); + + const expectedFileList = fs.readdirSync(path.join(__dirname, 'cases/escape-script-end-tag/expected/')); + const generatedFileList = fs.readdirSync(path.join(__dirname, 'cases/escape-script-end-tag/dist/')); + expect(expectedFileList.sort()).toEqual(generatedFileList.sort()); + + resolve(true); + }); + }); + + await webpackPromise; + }); + it('should build throw error if options passed to plugin is old options format', async () => { const initializedPlugin = () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-new diff --git a/__tests__/cases/escape-script-end-tag/expected/index.html b/__tests__/cases/escape-script-end-tag/expected/index.html new file mode 100644 index 0000000..218360a --- /dev/null +++ b/__tests__/cases/escape-script-end-tag/expected/index.html @@ -0,0 +1 @@ +
This is minimal code to demonstrate webpack usage
\ No newline at end of file diff --git a/__tests__/cases/escape-script-end-tag/fixtures/index.html b/__tests__/cases/escape-script-end-tag/fixtures/index.html new file mode 100644 index 0000000..c061c8e --- /dev/null +++ b/__tests__/cases/escape-script-end-tag/fixtures/index.html @@ -0,0 +1,14 @@ + + + + + + + + +This is minimal code to demonstrate webpack usage
+ + diff --git a/__tests__/cases/escape-script-end-tag/fixtures/index.js b/__tests__/cases/escape-script-end-tag/fixtures/index.js new file mode 100644 index 0000000..f2ceb4a --- /dev/null +++ b/__tests__/cases/escape-script-end-tag/fixtures/index.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-console +document.write(''); +document.write(''); diff --git a/__tests__/cases/escape-script-end-tag/webpack.config.ts b/__tests__/cases/escape-script-end-tag/webpack.config.ts new file mode 100644 index 0000000..e2ce706 --- /dev/null +++ b/__tests__/cases/escape-script-end-tag/webpack.config.ts @@ -0,0 +1,22 @@ +import path from 'path'; +import type { Configuration } from 'webpack'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import Self from '../../../dist'; + +const config: Configuration = { + mode: 'production', + entry: path.join(__dirname, './fixtures/index.js'), + output: { + path: path.join(__dirname, './dist'), + filename: '[name].js' + }, + plugins: [ + new HtmlWebpackPlugin({ + template: path.resolve(__dirname, './fixtures/index.html'), + inject: 'body' + }), + new Self() + ] +}; + +export default config; diff --git a/src/HtmlInlineScriptPlugin.ts b/src/HtmlInlineScriptPlugin.ts index 36346a2..4c64e3b 100644 --- a/src/HtmlInlineScriptPlugin.ts +++ b/src/HtmlInlineScriptPlugin.ts @@ -82,7 +82,8 @@ class HtmlInlineScriptPlugin implements WebpackPluginInstance { return { tagName: 'script', - innerHTML: asset.source() as string, + // escape '' appears in source + innerHTML: (asset.source() as string).replace(/(<)(\/script>)/g, '\\x3C$2'), voidTag: false, attributes: attributesWithoutSrc, meta: { plugin: 'html-inline-script-webpack-plugin' }