From 9498ee6bfeeec5b87eb86775dbb23f7ee4924030 Mon Sep 17 00:00:00 2001 From: Tilman Vatteroth Date: Thu, 17 Jun 2021 21:07:04 +0200 Subject: [PATCH 1/5] Remove cdn support Signed-off-by: Tilman Vatteroth --- app.js | 1 - docs/content/configuration.md | 1 - lib/config/default.js | 1 - lib/config/environment.js | 1 - lib/config/hackmdEnvironment.js | 1 - lib/config/oldDefault.js | 1 - lib/csp.js | 7 ----- public/views/hedgedoc/footer.ejs | 23 -------------- public/views/hedgedoc/head.ejs | 10 ------ public/views/index/footer.ejs | 11 ------- public/views/index/head.ejs | 10 ------ public/views/pretty.ejs | 28 ----------------- public/views/shared/polyfill.ejs | 7 ----- public/views/slide.ejs | 29 ------------------ test/csp.js | 16 ---------- webpack.common.js | 52 -------------------------------- 16 files changed, 199 deletions(-) delete mode 100644 public/views/shared/polyfill.ejs diff --git a/app.js b/app.js index 45e70c8b..878c8572 100644 --- a/app.js +++ b/app.js @@ -191,7 +191,6 @@ app.engine('ejs', ejs.renderFile) // set view engine app.set('view engine', 'ejs') // set generally available variables for all views -app.locals.useCDN = config.useCDN app.locals.serverURL = config.serverURL app.locals.sourceURL = config.sourceURL app.locals.allowAnonymous = config.allowAnonymous diff --git a/docs/content/configuration.md b/docs/content/configuration.md index c6e3fc3e..a19c749d 100644 --- a/docs/content/configuration.md +++ b/docs/content/configuration.md @@ -98,7 +98,6 @@ these are rarely used for various reasons. | config file | environment | **default** and example value | description | | --------------- | -------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `allowGravatar` | `CMD_ALLOW_GRAVATAR` | **`true`** or `false` | set to `false` to disable [Libravatar](https://www.libravatar.org/) as profile picture source on your instance. Libravatar is a federated open-source alternative to Gravatar. | -| `useCDN` | `CMD_USECDN` | **`false`** or `true` | set to use CDN resources or not (default is `false`) | ## Users and Privileges diff --git a/lib/config/default.js b/lib/config/default.js index c1f3f973..f98adf37 100644 --- a/lib/config/default.js +++ b/lib/config/default.js @@ -29,7 +29,6 @@ module.exports = { }, cookiePolicy: 'lax', protocolUseSSL: false, - useCDN: false, allowAnonymous: true, allowAnonymousEdits: false, allowFreeURL: false, diff --git a/lib/config/environment.js b/lib/config/environment.js index 1a43a88f..e9b711ff 100644 --- a/lib/config/environment.js +++ b/lib/config/environment.js @@ -27,7 +27,6 @@ module.exports = { cookiePolicy: process.env.CMD_COOKIE_POLICY, protocolUseSSL: toBooleanConfig(process.env.CMD_PROTOCOL_USESSL), allowOrigin: toArrayConfig(process.env.CMD_ALLOW_ORIGIN), - useCDN: toBooleanConfig(process.env.CMD_USECDN), allowAnonymous: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS), allowAnonymousEdits: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_EDITS), allowFreeURL: toBooleanConfig(process.env.CMD_ALLOW_FREEURL), diff --git a/lib/config/hackmdEnvironment.js b/lib/config/hackmdEnvironment.js index 76e41361..c40ffc96 100644 --- a/lib/config/hackmdEnvironment.js +++ b/lib/config/hackmdEnvironment.js @@ -20,7 +20,6 @@ module.exports = { }, protocolUseSSL: toBooleanConfig(process.env.HMD_PROTOCOL_USESSL), allowOrigin: toArrayConfig(process.env.HMD_ALLOW_ORIGIN), - useCDN: toBooleanConfig(process.env.HMD_USECDN), allowAnonymous: toBooleanConfig(process.env.HMD_ALLOW_ANONYMOUS), allowAnonymousEdits: toBooleanConfig(process.env.HMD_ALLOW_ANONYMOUS_EDITS), allowFreeURL: toBooleanConfig(process.env.HMD_ALLOW_FREEURL), diff --git a/lib/config/oldDefault.js b/lib/config/oldDefault.js index 738ad9f7..c9af5098 100644 --- a/lib/config/oldDefault.js +++ b/lib/config/oldDefault.js @@ -6,7 +6,6 @@ module.exports = { alloworigin: undefined, usessl: undefined, protocolusessl: undefined, - usecdn: undefined, allowanonymous: undefined, allowanonymousedits: undefined, allowfreeurl: undefined, diff --git a/lib/csp.js b/lib/csp.js index 74404413..76426d52 100644 --- a/lib/csp.js +++ b/lib/csp.js @@ -15,12 +15,6 @@ const defaultDirectives = { connectSrc: ['*'] } -const cdnDirectives = { - scriptSrc: ['https://cdnjs.cloudflare.com', 'https://cdn.mathjax.org'], - styleSrc: ['https://cdnjs.cloudflare.com', 'https://fonts.googleapis.com'], - fontSrc: ['https://cdnjs.cloudflare.com', 'https://fonts.gstatic.com'] -} - const disqusDirectives = { scriptSrc: ['https://disqus.com', 'https://*.disqus.com', 'https://*.disquscdn.com'], styleSrc: ['https://*.disquscdn.com'], @@ -39,7 +33,6 @@ CspStrategy.computeDirectives = function () { const directives = {} mergeDirectives(directives, config.csp.directives) mergeDirectivesIf(config.csp.addDefaults, directives, defaultDirectives) - mergeDirectivesIf(config.useCDN, directives, cdnDirectives) mergeDirectivesIf(config.csp.addDisqus, directives, disqusDirectives) mergeDirectivesIf(config.csp.addGoogleAnalytics, directives, googleAnalyticsDirectives) mergeDirectivesIf(config.dropbox.appKey, directives, dropboxDirectives) diff --git a/public/views/hedgedoc/footer.ejs b/public/views/hedgedoc/footer.ejs index 86572091..c3927db7 100644 --- a/public/views/hedgedoc/footer.ejs +++ b/public/views/hedgedoc/footer.ejs @@ -1,28 +1,5 @@ -<% if(useCDN) { %> - - - - - - - - - - - - - - - - - - - -<%- include('../build/index-scripts') %> -<% } else { %> <%- include('../build/index-pack-scripts') %> -<% } %> diff --git a/public/views/hedgedoc/head.ejs b/public/views/hedgedoc/head.ejs index 419d5dcc..c2321fcc 100644 --- a/public/views/hedgedoc/head.ejs +++ b/public/views/hedgedoc/head.ejs @@ -15,15 +15,5 @@ <% } %> <%= title %> -<% if(useCDN) { %> - - - - - -<%- include('../build/index-header') %> -<%- include('../shared/polyfill') %> -<% } else { %> <%- include('../build/index-pack-header') %> -<% } %> diff --git a/public/views/index/footer.ejs b/public/views/index/footer.ejs index c9532f6d..c6469cc0 100644 --- a/public/views/index/footer.ejs +++ b/public/views/index/footer.ejs @@ -1,12 +1 @@ -<% if(useCDN) { %> - - - - - - - -<%- include('../build/cover-scripts') %> -<% } else { %> <%- include('../build/cover-pack-scripts') %> -<% } %> diff --git a/public/views/index/head.ejs b/public/views/index/head.ejs index a6e79e35..a6751bbf 100644 --- a/public/views/index/head.ejs +++ b/public/views/index/head.ejs @@ -16,14 +16,4 @@ HedgeDoc - <%= __('Collaborative markdown notes') %> -<% if(useCDN) { %> - - - - - -<%- include('../build/cover-header') %> -<%- include('../shared/polyfill') %> -<% } else { %> <%- include('../build/cover-pack-header') %> -<% } %> diff --git a/public/views/pretty.ejs b/public/views/pretty.ejs index fc222cb8..97274ba1 100644 --- a/public/views/pretty.ejs +++ b/public/views/pretty.ejs @@ -25,17 +25,8 @@ <%= title %> <%- include('includes/favicon.ejs') %> - <% if(useCDN) { %> - - - - - <%- include('build/pretty-header') %> - <%- include('shared/polyfill') %> - <% } else { %> <%- include('build/pretty-pack-header') %> - <% } %> @@ -80,27 +71,8 @@ -<% if(useCDN) { %> - - - - - - - - - - - - - - - -<%- include('build/pretty-scripts') %> -<% } else { %> <%- include('build/pretty-pack-scripts') %> -<% } %> <%- include('shared/ga') %> diff --git a/public/views/shared/polyfill.ejs b/public/views/shared/polyfill.ejs deleted file mode 100644 index 82b2f025..00000000 --- a/public/views/shared/polyfill.ejs +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/public/views/slide.ejs b/public/views/slide.ejs index e08ca057..5837737c 100644 --- a/public/views/slide.ejs +++ b/public/views/slide.ejs @@ -14,19 +14,9 @@ <%= title %> <%- include('includes/favicon.ejs') %> - - <% if(useCDN) { %> - - - - - <%- include('build/slide-header') %> - <%- include('shared/polyfill') %> - <% } else { %> <%- include('build/slide-pack-header') %> - <% } %> <% if(typeof theme !== 'undefined' && theme) { %> @@ -87,29 +77,10 @@ - <% if(useCDN) { %> - - - - - - - - - - - - - - - - <%- include('build/slide-scripts') %> - <% } else { %> <%- include('build/slide-pack-scripts') %> - <% } %> diff --git a/test/csp.js b/test/csp.js index 15412022..02184662 100644 --- a/test/csp.js +++ b/test/csp.js @@ -27,7 +27,6 @@ describe('Content security policies', function () { upgradeInsecureRequests: 'auto', reportURI: undefined }, - useCDN: true, dropbox: { appKey: undefined } @@ -44,21 +43,6 @@ describe('Content security policies', function () { csp = mock.reRequire('../lib/csp') }) - // beginnging Tests - it('Disable CDN', function () { - const testconfig = defaultConfig - testconfig.useCDN = false - mock('../lib/config', testconfig) - csp = mock.reRequire('../lib/csp') - - assert(!csp.computeDirectives().scriptSrc.includes('https://cdnjs.cloudflare.com')) - assert(!csp.computeDirectives().scriptSrc.includes('https://cdn.mathjax.org')) - assert(!csp.computeDirectives().styleSrc.includes('https://cdnjs.cloudflare.com')) - assert(!csp.computeDirectives().styleSrc.includes('https://fonts.googleapis.com')) - assert(!csp.computeDirectives().fontSrc.includes('https://cdnjs.cloudflare.com')) - assert(!csp.computeDirectives().fontSrc.includes('https://fonts.gstatic.com')) - }) - it('Disable Google Analytics', function () { const testconfig = defaultConfig testconfig.csp.addGoogleAnalytics = false diff --git a/webpack.common.js b/webpack.common.js index 48b5bf14..70175c39 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -22,13 +22,6 @@ module.exports = { 'moment': 'moment', CodeMirror: 'codemirror/lib/codemirror.js' }), - new HtmlWebpackPlugin({ - template: 'public/views/includes/header.ejs', - chunks: ['font', 'index-styles', 'index'], - filename: path.join(__dirname, 'public/views/build/index-header.ejs'), - inject: false, - chunksSortMode: 'manual' - }), new HtmlWebpackPlugin({ template: 'public/views/includes/header.ejs', chunks: ['font-pack', 'index-styles-pack', 'index-styles', 'index'], @@ -36,12 +29,6 @@ module.exports = { inject: false, chunksSortMode: 'manual' }), - new HtmlWebpackPlugin({ - template: 'public/views/includes/scripts.ejs', - chunks: ['index'], - filename: path.join(__dirname, 'public/views/build/index-scripts.ejs'), - inject: false - }), new HtmlWebpackPlugin({ template: 'public/views/includes/scripts.ejs', chunks: ['common', 'index-pack'], @@ -49,13 +36,6 @@ module.exports = { inject: false, chunksSortMode: 'manual' }), - new HtmlWebpackPlugin({ - template: 'public/views/includes/header.ejs', - chunks: ['font', 'cover'], - filename: path.join(__dirname, 'public/views/build/cover-header.ejs'), - inject: false, - chunksSortMode: 'manual' - }), new HtmlWebpackPlugin({ template: 'public/views/includes/header.ejs', chunks: ['font-pack', 'cover-styles-pack', 'cover'], @@ -63,12 +43,6 @@ module.exports = { inject: false, chunksSortMode: 'manual' }), - new HtmlWebpackPlugin({ - template: 'public/views/includes/scripts.ejs', - chunks: ['cover'], - filename: path.join(__dirname, 'public/views/build/cover-scripts.ejs'), - inject: false - }), new HtmlWebpackPlugin({ template: 'public/views/includes/scripts.ejs', chunks: ['common', 'cover-pack'], @@ -76,13 +50,6 @@ module.exports = { inject: false, chunksSortMode: 'manual' }), - new HtmlWebpackPlugin({ - template: 'public/views/includes/header.ejs', - chunks: ['font', 'pretty-styles', 'pretty'], - filename: path.join(__dirname, 'public/views/build/pretty-header.ejs'), - inject: false, - chunksSortMode: 'manual' - }), new HtmlWebpackPlugin({ template: 'public/views/includes/header.ejs', chunks: ['font-pack', 'pretty-styles-pack', 'pretty-styles', 'pretty'], @@ -90,12 +57,6 @@ module.exports = { inject: false, chunksSortMode: 'manual' }), - new HtmlWebpackPlugin({ - template: 'public/views/includes/scripts.ejs', - chunks: ['pretty'], - filename: path.join(__dirname, 'public/views/build/pretty-scripts.ejs'), - inject: false - }), new HtmlWebpackPlugin({ template: 'public/views/includes/scripts.ejs', chunks: ['common', 'pretty-pack'], @@ -103,13 +64,6 @@ module.exports = { inject: false, chunksSortMode: 'manual' }), - new HtmlWebpackPlugin({ - template: 'public/views/includes/header.ejs', - chunks: ['font', 'slide-styles', 'slide'], - filename: path.join(__dirname, 'public/views/build/slide-header.ejs'), - inject: false, - chunksSortMode: 'manual' - }), new HtmlWebpackPlugin({ template: 'public/views/includes/header.ejs', chunks: ['font-pack', 'slide-styles-pack', 'slide-styles', 'slide'], @@ -117,12 +71,6 @@ module.exports = { inject: false, chunksSortMode: 'manual' }), - new HtmlWebpackPlugin({ - template: 'public/views/includes/scripts.ejs', - chunks: ['slide'], - filename: path.join(__dirname, 'public/views/build/slide-scripts.ejs'), - inject: false - }), new HtmlWebpackPlugin({ template: 'public/views/includes/scripts.ejs', chunks: ['slide-pack'], From 3b0060187294e9d4b64892c735c9ca68d31f6804 Mon Sep 17 00:00:00 2001 From: David Mehren Date: Mon, 21 Jun 2021 20:14:29 +0200 Subject: [PATCH 2/5] Inline CSS & JS into HTML export template Previously, the HTML export template `html.hbs` included CDN links for the HTML and CSS resources. This commit enables Webpack to create a new `htmlexport.html` at build-time, which includes all resources inline. That template is then used as before by the frontend to be populated with the rendered note content. The tradeoff is that each exported .html file is about 5.6 MB in size, as we need to inline all fonts (icons & emojis). Signed-off-by: David Mehren --- public/js/extra.js | 25 ++++++++++------------- public/js/htmlExport.js | 21 ++++++++++++++++++- public/views/{html.hbs => htmlexport.ejs} | 21 ++----------------- webpack.htmlexport.js | 20 +++++++++++++++--- webpack.prod.js | 3 +++ 5 files changed, 53 insertions(+), 37 deletions(-) rename public/views/{html.hbs => htmlexport.ejs} (71%) diff --git a/public/js/extra.js b/public/js/extra.js index 6e3b0ed0..c72007b6 100644 --- a/public/js/extra.js +++ b/public/js/extra.js @@ -681,21 +681,18 @@ export function exportToHTML (view) { const tocAffix = $('#ui-toc-affix').clone() tocAffix.find('*').removeClass('active').find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll') // generate html via template - $.get(`${serverurl}/build/html.min.css`, css => { - $.get(`${serverurl}/views/html.hbs`, template => { - let html = template.replace('{{{url}}}', serverurl) - html = html.replace('{{title}}', title) - html = html.replace('{{{css}}}', css) - html = html.replace('{{{html}}}', src[0].outerHTML) - html = html.replace('{{{ui-toc}}}', toc.html()) - html = html.replace('{{{ui-toc-affix}}}', tocAffix.html()) - html = html.replace('{{{lang}}}', (md && md.meta && md.meta.lang) ? `lang="${md.meta.lang}"` : '') - html = html.replace('{{{dir}}}', (md && md.meta && md.meta.dir) ? `dir="${md.meta.dir}"` : '') - const blob = new Blob([html], { - type: 'text/html;charset=utf-8' - }) - saveAs(blob, filename, true) + $.get(`${serverurl}/build/htmlexport.html`, template => { + let html = template.replace('{{{url}}}', serverurl) + html = html.replace('{{title}}', title) + html = html.replace('{{{html}}}', src[0].outerHTML) + html = html.replace('{{{ui-toc}}}', toc.html()) + html = html.replace('{{{ui-toc-affix}}}', tocAffix.html()) + html = html.replace('{{{lang}}}', (md && md.meta && md.meta.lang) ? `lang="${md.meta.lang}"` : '') + html = html.replace('{{{dir}}}', (md && md.meta && md.meta.dir) ? `dir="${md.meta.dir}"` : '') + const blob = new Blob([html], { + type: 'text/html;charset=utf-8' }) + saveAs(blob, filename, true) }) } diff --git a/public/js/htmlExport.js b/public/js/htmlExport.js index 1a873aca..676e2b1b 100644 --- a/public/js/htmlExport.js +++ b/public/js/htmlExport.js @@ -1,6 +1,25 @@ +require('bootstrap/dist/css/bootstrap.min.css') +require('fork-awesome/css/fork-awesome.min.css') +require('ionicons/css/ionicons.min.css') +require('prismjs/prism') +require('prismjs/themes/prism.css') +require('prismjs/components/prism-wiki') +require('prismjs/components/prism-haskell') +require('prismjs/components/prism-go') +require('prismjs/components/prism-typescript') +require('prismjs/components/prism-jsx') +require('prismjs/components/prism-makefile') +require('prismjs/components/prism-gherkin') +require('highlight.js/styles/github-gist.css') +require('emojify.js/dist/css/basic/emojify.min.css') require('../css/github-extract.css') require('../css/markdown.css') require('../css/extra.css') require('../css/slide-preview.css') -require('../css/google-font.css') +require('../css/font.css') require('../css/site.css') +const $ = require('jquery') +window.jQuery = $ +window.$ = $ +require('bootstrap') +require('gist-embed/gist-embed.min') diff --git a/public/views/html.hbs b/public/views/htmlexport.ejs similarity index 71% rename from public/views/html.hbs rename to public/views/htmlexport.ejs index 7e8268ba..ee83d850 100644 --- a/public/views/html.hbs +++ b/public/views/htmlexport.ejs @@ -19,22 +19,7 @@ - - - - - - - - - - + <% _.forEach(htmlWebpackPlugin.files.css, function(cssFile) { %><% }); %> @@ -52,9 +37,7 @@ - - - + <% _.forEach(htmlWebpackPlugin.files.js, function(jsFile) { %><% }); %>