mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-21 09:16:30 -05:00
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 <git@herrmehren.de>
This commit is contained in:
parent
9498ee6bfe
commit
3b00601872
5 changed files with 53 additions and 37 deletions
|
@ -681,21 +681,18 @@ export function exportToHTML (view) {
|
||||||
const tocAffix = $('#ui-toc-affix').clone()
|
const tocAffix = $('#ui-toc-affix').clone()
|
||||||
tocAffix.find('*').removeClass('active').find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll')
|
tocAffix.find('*').removeClass('active').find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll')
|
||||||
// generate html via template
|
// generate html via template
|
||||||
$.get(`${serverurl}/build/html.min.css`, css => {
|
$.get(`${serverurl}/build/htmlexport.html`, template => {
|
||||||
$.get(`${serverurl}/views/html.hbs`, template => {
|
let html = template.replace('{{{url}}}', serverurl)
|
||||||
let html = template.replace('{{{url}}}', serverurl)
|
html = html.replace('{{title}}', title)
|
||||||
html = html.replace('{{title}}', title)
|
html = html.replace('{{{html}}}', src[0].outerHTML)
|
||||||
html = html.replace('{{{css}}}', css)
|
html = html.replace('{{{ui-toc}}}', toc.html())
|
||||||
html = html.replace('{{{html}}}', src[0].outerHTML)
|
html = html.replace('{{{ui-toc-affix}}}', tocAffix.html())
|
||||||
html = html.replace('{{{ui-toc}}}', toc.html())
|
html = html.replace('{{{lang}}}', (md && md.meta && md.meta.lang) ? `lang="${md.meta.lang}"` : '')
|
||||||
html = html.replace('{{{ui-toc-affix}}}', tocAffix.html())
|
html = html.replace('{{{dir}}}', (md && md.meta && md.meta.dir) ? `dir="${md.meta.dir}"` : '')
|
||||||
html = html.replace('{{{lang}}}', (md && md.meta && md.meta.lang) ? `lang="${md.meta.lang}"` : '')
|
const blob = new Blob([html], {
|
||||||
html = html.replace('{{{dir}}}', (md && md.meta && md.meta.dir) ? `dir="${md.meta.dir}"` : '')
|
type: 'text/html;charset=utf-8'
|
||||||
const blob = new Blob([html], {
|
|
||||||
type: 'text/html;charset=utf-8'
|
|
||||||
})
|
|
||||||
saveAs(blob, filename, true)
|
|
||||||
})
|
})
|
||||||
|
saveAs(blob, filename, true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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/github-extract.css')
|
||||||
require('../css/markdown.css')
|
require('../css/markdown.css')
|
||||||
require('../css/extra.css')
|
require('../css/extra.css')
|
||||||
require('../css/slide-preview.css')
|
require('../css/slide-preview.css')
|
||||||
require('../css/google-font.css')
|
require('../css/font.css')
|
||||||
require('../css/site.css')
|
require('../css/site.css')
|
||||||
|
const $ = require('jquery')
|
||||||
|
window.jQuery = $
|
||||||
|
window.$ = $
|
||||||
|
require('bootstrap')
|
||||||
|
require('gist-embed/gist-embed.min')
|
||||||
|
|
|
@ -19,22 +19,7 @@
|
||||||
<link rel="mask-icon" href="{{{url}}}/icons/safari-pinned-tab.svg" color="#b51f08">
|
<link rel="mask-icon" href="{{{url}}}/icons/safari-pinned-tab.svg" color="#b51f08">
|
||||||
<link rel="shortcut icon" href="{{{url}}}/icons/favicon.ico">
|
<link rel="shortcut icon" href="{{{url}}}/icons/favicon.ico">
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" integrity="sha256-H0KfTigpUV+0/5tn2HXC0CPwhhDhWgSawJdnFd0CGCo=" crossorigin="anonymous" />
|
<% _.forEach(htmlWebpackPlugin.files.css, function(cssFile) { %><style><%= compilation.assets[cssFile.substr(htmlWebpackPlugin.files.publicPath.length)].source() %></style><% }); %>
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.3/css/fork-awesome.min.css" integrity="sha256-ZhApazu+kejqTYhMF+1DzNKjIzP7KXu6AzyXcC1gMus=" crossorigin="anonymous" />
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" integrity="sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=" crossorigin="anonymous" />
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.1/themes/prism.min.css" integrity="sha256-vtR0hSWRc3Tb26iuN2oZHt3KRUomwTufNIf5/4oeCyg=" crossorigin="anonymous" />
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github-gist.min.css" integrity="sha256-tAflq+ymku3Khs+I/WcAneIlafYgDiOQ9stIHH985Wo=" crossorigin="anonymous" />
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/css/basic/emojify.min.css" integrity="sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=" crossorigin="anonymous" />
|
|
||||||
<style>
|
|
||||||
{{{css}}}
|
|
||||||
</style>
|
|
||||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
|
||||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
|
||||||
<!--[if lt IE 9]>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js" integrity="sha256-3Jy/GbSLrg0o9y5Z5n1uw0qxZECH7C6OQpVBgNFYa0g=" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js" integrity="sha256-g6iAfvZp+nDQ2TdTR/VVKJf3bGro4ub5fvWSWVRi2NE=" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js" integrity="sha256-8E4Is26QH0bD52WoQpcB+R/tcWQtpzlCojrybUd7Mxo=" crossorigin="anonymous"></script>
|
|
||||||
<![endif]-->
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body translate="no">
|
<body translate="no">
|
||||||
|
@ -52,9 +37,7 @@
|
||||||
<div id="ui-toc-affix" class="ui-affix-toc ui-toc-dropdown unselectable hidden-print" data-spy="affix" style="top:17px;display:none;" {{{lang}}} {{{dir}}}>
|
<div id="ui-toc-affix" class="ui-affix-toc ui-toc-dropdown unselectable hidden-print" data-spy="affix" style="top:17px;display:none;" {{{lang}}} {{{dir}}}>
|
||||||
{{{ui-toc-affix}}}
|
{{{ui-toc-affix}}}
|
||||||
</div>
|
</div>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
|
<% _.forEach(htmlWebpackPlugin.files.js, function(jsFile) { %><script><%= compilation.assets[jsFile.substr(htmlWebpackPlugin.files.publicPath.length)].source() %></script><% }); %>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js" integrity="sha256-kJrlY+s09+QoWjpkOrXXwhxeaoDz9FW5SaxF8I0DibQ=" crossorigin="anonymous" defer></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js" integrity="sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=" crossorigin="anonymous" defer></script>
|
|
||||||
<script>
|
<script>
|
||||||
var markdown = $(".markdown-body");
|
var markdown = $(".markdown-body");
|
||||||
//smooth all hash trigger scrolling
|
//smooth all hash trigger scrolling
|
|
@ -1,5 +1,6 @@
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'save-as-html',
|
name: 'save-as-html',
|
||||||
|
@ -10,6 +11,14 @@ module.exports = {
|
||||||
rules: [{
|
rules: [{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
use: [MiniCssExtractPlugin.loader, 'css-loader']
|
use: [MiniCssExtractPlugin.loader, 'css-loader']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'url-loader'
|
||||||
|
}
|
||||||
|
]
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
@ -18,8 +27,13 @@ module.exports = {
|
||||||
filename: '[name].js'
|
filename: '[name].js'
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new MiniCssExtractPlugin({
|
new HtmlWebpackPlugin({
|
||||||
filename: 'html.min.css'
|
// Load a custom template (uses lodash templating)
|
||||||
})
|
template: 'public/views/htmlexport.ejs',
|
||||||
|
filename: 'htmlexport.html',
|
||||||
|
inject: false,
|
||||||
|
cache: false
|
||||||
|
}),
|
||||||
|
new MiniCssExtractPlugin({ filename: 'htmlexport.css' })
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@ module.exports = [
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
optimization: {
|
optimization: {
|
||||||
minimizer: [
|
minimizer: [
|
||||||
|
new ESBuildMinifyPlugin({
|
||||||
|
target: 'es2015'
|
||||||
|
}),
|
||||||
new OptimizeCSSAssetsPlugin({})
|
new OptimizeCSSAssetsPlugin({})
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue