From 11b6a42bb655b3f2931ed494a58a616c675a467e Mon Sep 17 00:00:00 2001 From: Jack Westbrook Date: Wed, 17 Jan 2024 09:53:24 +0100 Subject: [PATCH] fix(vite): escape angular template html and load as strings --- package.json | 2 ++ public/app/angular/index.ts | 3 +- public/app/angular/partials.ts | 9 ++---- vite.config.ts | 56 +++++++++++++++++++++------------- yarn.lock | 37 ++++++++++++++++++++-- 5 files changed, 74 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 28f10d5d804..eac9e386c45 100644 --- a/package.json +++ b/package.json @@ -117,6 +117,7 @@ "@types/google.analytics": "^0.0.46", "@types/gtag.js": "^0.0.20", "@types/history": "4.7.11", + "@types/html-minifier-terser": "^7", "@types/ini": "^4", "@types/jest": "29.5.14", "@types/jquery": "3.5.32", @@ -185,6 +186,7 @@ "eslint-scope": "^8.1.0", "fishery": "^2.2.2", "glob": "11.0.1", + "html-minifier-terser": "^7.2.0", "http-server": "14.1.1", "i18next-parser": "9.3.0", "ini": "^5.0.0", diff --git a/public/app/angular/index.ts b/public/app/angular/index.ts index c4d52f43160..3fbf6ae93f2 100644 --- a/public/app/angular/index.ts +++ b/public/app/angular/index.ts @@ -1,6 +1,5 @@ import './panel/all'; -// Vite: these partials still aren't working correctly so comment out for now. -// import './partials'; +import './partials'; import './filters/filters'; import './services/alert_srv'; import './services/dynamic_directive_srv'; diff --git a/public/app/angular/partials.ts b/public/app/angular/partials.ts index 9a4703ba7e5..523a32ef867 100644 --- a/public/app/angular/partials.ts +++ b/public/app/angular/partials.ts @@ -1,10 +1,5 @@ -// TODO: Vite has no require.context support yet. Attempt at a workaround below. -// let templates = (require as any).context('../', true, /\.html$/); -// templates.keys().forEach((key: string) => { -// templates(key); -// }); - -// See vite.config.ts angularHtmlImport function for the code that _should_ assist with these templates. +// TODO: Vite has no require.context support so we're importing them individually here. +// See the vite.config.ts angularHtmlImport plugin for the code that compiles these templates. import 'app/angular/panel/partials/query_editor_row.html'; import 'app/angular/partials/http_settings_next.html'; diff --git a/vite.config.ts b/vite.config.ts index 0b0b10d907f..59acae86edc 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,32 +1,11 @@ import react from '@vitejs/plugin-react-swc'; +import { minify } from 'html-minifier-terser'; import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { defineConfig } from 'vite'; const require = createRequire(import.meta.url); -// This is a Vite plugin for handling angular templates. -// https://vitejs.dev/guide/api-plugin.html#simple-examples - -// The webpack output from https://github.com/WearyMonkey/ngtemplate-loader looks like this: -// var code = "\n
\n\t
\n\t\t
\n\t\t
\n\n\t\t
\n\t\t\tAdd annotation\n\t\t\tEdit annotation\n\t\t
\n\n
{{ctrl.timeFormated}}
\n\t
\n\n\t
\n\t\t
\n\t\t\t
\n\t\t\t\tDescription\n\t\t\t\t\n\t\t\t
\n\n\t\t\t
\n\t\t\t\tTags\n\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tCancel\n\t\t\t
\n\t\t
\n\t
\n
\n"; -// Exports -// var _module_exports =code;; -// var path = 'public/app/features/annotations/partials/event_editor.html'; -// window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, _module_exports) }]); -// module.exports = path; -function angularHtmlImport() { - return { - name: 'transform-angular-html', - transform(src, id) { - if (/^.*\.html$/g.test(id)) { - const result = `let path = '${id}'; angular.module('ng').run(['$templateCache', c => { c.put(path, \`${src}\`) }]); export default path;`; - return { code: result, map: null }; - } - }, - }; -} - // https://vitejs.dev/config/ export default defineConfig({ root: './public', @@ -85,3 +64,36 @@ export default defineConfig({ extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json'], }, }); + +// This is a Vite plugin for handling angular templates. +// https://vitejs.dev/guide/api-plugin.html#simple-examples + +// The webpack output from https://github.com/WearyMonkey/ngtemplate-loader looks like this: +// var code = "\n
\n\t
\n\t\t
\n\t\t
\n\n\t\t
\n\t\t\tAdd annotation\n\t\t\tEdit annotation\n\t\t
\n\n
{{ctrl.timeFormated}}
\n\t
\n\n\t
\n\t\t
\n\t\t\t
\n\t\t\t\tDescription\n\t\t\t\t\n\t\t\t
\n\n\t\t\t
\n\t\t\t\tTags\n\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tCancel\n\t\t\t
\n\t\t
\n\t
\n
\n"; +// Exports +// var _module_exports =code;; +// var path = 'public/app/features/annotations/partials/event_editor.html'; +// window.angular.module('ng').run(['$templateCache', function(c) { c.put(path, _module_exports) }]); +// module.exports = path; +function angularHtmlImport() { + return { + name: 'transform-angular-html', + async transform(src, id) { + if (/^.*\.html$/g.test(id)) { + const minifierOptions = { + collapseWhitespace: false, + collapseBooleanAttributes: true, + conservativeCollapse: true, + minifyJS: true, + }; + + const idParts = id.split('/public/'); + const path = idParts[idParts.length - 1]; + const html = await minify(src, minifierOptions); + const stringified = JSON.stringify(html); + const result = `let path = 'public/${path}'; angular.module('ng').run(['$templateCache', c => { c.put(path, ${stringified}) }]); export default path;`; + return { code: result, map: null }; + } + }, + }; +} diff --git a/yarn.lock b/yarn.lock index e819d8a2088..9d7b010164e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10279,6 +10279,13 @@ __metadata: languageName: node linkType: hard +"@types/html-minifier-terser@npm:^7": + version: 7.0.2 + resolution: "@types/html-minifier-terser@npm:7.0.2" + checksum: 10/312d9285b034538fc8c851d99b5cc47f83e802f0dccc1be4adf10d4ee881d92d14f97ca1862313a827b844a7f71db6ab80198d7741f1747a9bcf7de77181ce40 + languageName: node + linkType: hard + "@types/ini@npm:^4": version: 4.1.1 resolution: "@types/ini@npm:4.1.1" @@ -13413,7 +13420,7 @@ __metadata: languageName: node linkType: hard -"clean-css@npm:^5.1.5": +"clean-css@npm:^5.1.5, clean-css@npm:~5.3.2": version: 5.3.3 resolution: "clean-css@npm:5.3.3" dependencies: @@ -13743,6 +13750,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^10.0.0": + version: 10.0.1 + resolution: "commander@npm:10.0.1" + checksum: 10/8799faa84a30da985802e661cc9856adfaee324d4b138413013ef7f087e8d7924b144c30a1f1405475f0909f467665cd9e1ce13270a2f41b141dab0b7a58f3fb + languageName: node + linkType: hard + "commander@npm:^12.1.0": version: 12.1.0 resolution: "commander@npm:12.1.0" @@ -18257,6 +18271,7 @@ __metadata: "@types/google.analytics": "npm:^0.0.46" "@types/gtag.js": "npm:^0.0.20" "@types/history": "npm:4.7.11" + "@types/html-minifier-terser": "npm:^7" "@types/ini": "npm:^4" "@types/jest": "npm:29.5.14" "@types/jquery": "npm:3.5.32" @@ -18355,6 +18370,7 @@ __metadata: fishery: "npm:^2.2.2" glob: "npm:11.0.1" history: "npm:4.10.1" + html-minifier-terser: "npm:^7.2.0" http-server: "npm:14.1.1" i18next: "npm:^24.0.0" i18next-browser-languagedetector: "npm:^8.0.0" @@ -18826,6 +18842,23 @@ __metadata: languageName: node linkType: hard +"html-minifier-terser@npm:^7.2.0": + version: 7.2.0 + resolution: "html-minifier-terser@npm:7.2.0" + dependencies: + camel-case: "npm:^4.1.2" + clean-css: "npm:~5.3.2" + commander: "npm:^10.0.0" + entities: "npm:^4.4.0" + param-case: "npm:^3.0.4" + relateurl: "npm:^0.2.7" + terser: "npm:^5.15.1" + bin: + html-minifier-terser: cli.js + checksum: 10/7320095dbf08c361b45e855bd840d1d21fe86326afee775503594163532ebaaed9bb1c9dc98232b03c169dc24b56f30c294d559bca0cade59f9c950a1992db82 + languageName: node + linkType: hard + "html-parse-stringify@npm:^3.0.1": version: 3.0.1 resolution: "html-parse-stringify@npm:3.0.1" @@ -29466,7 +29499,7 @@ __metadata: languageName: node linkType: hard -"terser@npm:^5.17.4, terser@npm:^5.26.0, terser@npm:^5.7.2": +"terser@npm:^5.15.1, terser@npm:^5.17.4, terser@npm:^5.26.0, terser@npm:^5.7.2": version: 5.29.2 resolution: "terser@npm:5.29.2" dependencies: