website/webpack.base.js
2021-10-07 14:04:30 +09:00

163 lines
3.6 KiB
JavaScript

const path = require('path');
const fs = require('fs');
const marked = require('marked');
const CopyPlugin = require('copy-webpack-plugin');
// const CompressionPlugin = require("compression-webpack-plugin")
const renderer = new marked.Renderer()
renderer.link = (href, title, text) => {
if(href === null)
{
return text
}
let out = '<a href="' + href + '"'
if(title)
{
out += ' title="' + title + '"'
}
if(href.startsWith('http'))
{
out += ' target="_blank" rel="noreferrer noopener nofollow"'
}
out += '>' + text + '</a>'
return out
}
renderer.image = (href, title, text) => {
if (href === null) {
return text;
}
let out = '<img src="' + href + '" alt="' + text + '"';
if (title) {
out += ' title="' + title + '"';
}
else
{
out += ' title="' + text + '"';
}
out += ' onclick="open_image(\'' + href + '\')" />';
return out;
}
marked.setOptions({ renderer: renderer })
class BlogListingPlugin
{
static default_options = {
output_file: 'blog_list.json',
}
constructor(options = {})
{
this.options = {...BlogListingPlugin.default_options, ...options}
}
apply(compiler)
{
const plugin_name = BlogListingPlugin.name
const { webpack } = compiler
compiler.hooks.thisCompilation.tap(
plugin_name,
(compilation) => {
compilation.hooks.processAssets.tapAsync(
{
name: plugin_name,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE
},
(compilationAssets, callback) => {
let content = []
Object.keys(compilationAssets).forEach((file_path) => {
if(file_path.startsWith('blog') && file_path.endsWith('.md'))
{
const file_name = path.basename(file_path).slice(0, -3)
const blog_info = path.basename(path.dirname(file_path)).split('_')
const blog_date = blog_info[0]
const blog_entry = blog_info.slice(1).join('_')
compilation.emitAsset(
'blog/' + blog_date + '_' + blog_entry + '/' + file_name + '.html',
new webpack.sources.RawSource(
marked(
new TextDecoder('utf-8').decode(compilationAssets[file_path].source()))))
content.push({
name: file_name,
date: blog_date
})
}
})
content.sort((x1, x2) => { x1.create_date < x2.create_date })
compilation.emitAsset(
this.options.output_file, new webpack.sources.RawSource(JSON.stringify(content)))
return callback();
}
)
}
)
}
}
module.exports = {
mode: "none",
entry: './src/index.jsx',
module:
{
rules: [
{
test: /\.jsx$/,
exclude: /node_modules/,
use: [{
loader: "babel-loader",
options:
{
presets: ["@babel/preset-env"],
plugins: [
["babel-plugin-inferno",
{
"imports": true
}]
]
}
}]
},
{
test: /src.*\.s[ac]ss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /src.*\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.svg$/,
type: "asset/inline"
}
]
},
plugins: [
new BlogListingPlugin(),
new CopyPlugin({
patterns: [
{from: 'index.html'},
{from: 'robot.txt'},
{from: 'src/lang', to: 'lang'},
{from: 'assets/blog', to: 'blog'},
{from: 'assets/icons', to: 'assets/icons'},
{from: 'assets/images', to: 'assets/images'},
{from: 'assets/theme', to: 'assets/theme'}
]}),
// new CompressionPlugin(
// {
// filename: "[path].gz[query]",
// algorithm: "gzip",
// test: [/\.js/, /\.svg/],
// threshold: 1000
// })
],
output:
{
filename: 'bundle.js',
path: path.resolve(__dirname, 'public'),
assetModuleFilename: 'assets/[query].[ext]',
clean: true
}
};