2021-04-08 13:41:57 +03:00
import fastGlob from 'fast-glob' ;
import wrapAnsi from 'wrap-ansi' ;
import AddAssetPlugin from 'add-asset-webpack-plugin' ;
import LicenseCheckerWebpackPlugin from 'license-checker-webpack-plugin' ;
import MiniCssExtractPlugin from 'mini-css-extract-plugin' ;
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin' ;
2022-10-01 17:26:38 +03:00
import { VueLoaderPlugin } from 'vue-loader' ;
2021-04-15 23:07:31 +03:00
import EsBuildLoader from 'esbuild-loader' ;
2022-06-06 06:27:25 +03:00
import { parse , dirname } from 'path' ;
2021-04-08 13:41:57 +03:00
import webpack from 'webpack' ;
import { fileURLToPath } from 'url' ;
2022-09-04 01:20:46 +03:00
import { readFileSync } from 'fs' ;
2021-04-08 13:41:57 +03:00
2021-04-15 23:07:31 +03:00
const { ESBuildMinifyPlugin } = EsBuildLoader ;
2021-04-08 13:41:57 +03:00
const { SourceMapDevToolPlugin } = webpack ;
2022-09-08 00:35:54 +03:00
const formatLicenseText = ( licenseText ) => wrapAnsi ( licenseText || '' , 80 ) . trim ( ) ;
2022-06-06 06:27:25 +03:00
const glob = ( pattern ) => fastGlob . sync ( pattern , {
cwd : dirname ( fileURLToPath ( new URL ( import . meta . url ) ) ) ,
absolute : true ,
} ) ;
2020-02-11 20:02:41 +03:00
2020-01-28 10:30:39 +03:00
const themes = { } ;
2020-02-11 20:02:41 +03:00
for ( const path of glob ( 'web_src/less/themes/*.less' ) ) {
2020-01-28 10:30:39 +03:00
themes [ parse ( path ) . name ] = [ path ] ;
}
2019-11-13 17:52:13 +03:00
2020-02-23 11:47:42 +03:00
const isProduction = process . env . NODE _ENV !== 'development' ;
2020-07-28 00:01:25 +03:00
const filterCssImport = ( url , ... args ) => {
const cssFile = args [ 1 ] || args [ 0 ] ; // resourcePath is 2nd argument for url and 3rd for import
2020-06-28 05:59:56 +03:00
const importedFile = url . replace ( /[?#].+/ , '' ) . toLowerCase ( ) ;
2020-07-06 11:56:54 +03:00
2020-06-28 05:59:56 +03:00
if ( cssFile . includes ( 'fomantic' ) ) {
if ( /brand-icons/ . test ( importedFile ) ) return false ;
2020-07-12 12:10:56 +03:00
if ( /(eot|ttf|otf|woff|svg)$/ . test ( importedFile ) ) return false ;
2020-07-06 11:56:54 +03:00
}
2022-09-13 19:33:37 +03:00
if ( cssFile . includes ( 'katex' ) && /(ttf|woff)$/ . test ( importedFile ) ) {
return false ;
}
2020-12-27 17:24:27 +03:00
if ( cssFile . includes ( 'font-awesome' ) && /(eot|ttf|otf|woff|svg)$/ . test ( importedFile ) ) {
return false ;
2020-06-28 05:59:56 +03:00
}
2020-07-06 11:56:54 +03:00
return true ;
2020-06-28 05:59:56 +03:00
} ;
2022-11-18 20:01:06 +03:00
/** @type {import("webpack").Configuration} */
2021-04-08 13:41:57 +03:00
export default {
2020-02-23 11:47:42 +03:00
mode : isProduction ? 'production' : 'development' ,
2019-11-13 17:52:13 +03:00
entry : {
2020-01-28 10:30:39 +03:00
index : [
2022-06-06 06:27:25 +03:00
fileURLToPath ( new URL ( 'web_src/js/jquery.js' , import . meta . url ) ) ,
fileURLToPath ( new URL ( 'web_src/fomantic/build/semantic.js' , import . meta . url ) ) ,
fileURLToPath ( new URL ( 'web_src/js/index.js' , import . meta . url ) ) ,
fileURLToPath ( new URL ( 'node_modules/easymde/dist/easymde.min.css' , import . meta . url ) ) ,
fileURLToPath ( new URL ( 'web_src/fomantic/build/semantic.css' , import . meta . url ) ) ,
fileURLToPath ( new URL ( 'web_src/less/index.less' , import . meta . url ) ) ,
2020-01-28 10:30:39 +03:00
] ,
swagger : [
2022-06-06 06:27:25 +03:00
fileURLToPath ( new URL ( 'web_src/js/standalone/swagger.js' , import . meta . url ) ) ,
fileURLToPath ( new URL ( 'web_src/less/standalone/swagger.less' , import . meta . url ) ) ,
2020-01-28 10:30:39 +03:00
] ,
2020-05-22 04:45:34 +03:00
serviceworker : [
2022-06-06 06:27:25 +03:00
fileURLToPath ( new URL ( 'web_src/js/serviceworker.js' , import . meta . url ) ) ,
2020-05-22 04:45:34 +03:00
] ,
2020-07-03 12:55:36 +03:00
'eventsource.sharedworker' : [
2022-06-06 06:27:25 +03:00
fileURLToPath ( new URL ( 'web_src/js/features/eventsource.sharedworker.js' , import . meta . url ) ) ,
2020-07-03 12:55:36 +03:00
] ,
2020-01-28 10:30:39 +03:00
... themes ,
2019-11-13 17:52:13 +03:00
} ,
2020-01-14 21:02:08 +03:00
devtool : false ,
2019-11-13 17:52:13 +03:00
output : {
2022-06-06 06:27:25 +03:00
path : fileURLToPath ( new URL ( 'public' , import . meta . url ) ) ,
2020-05-22 04:45:34 +03:00
filename : ( { chunk } ) => {
// serviceworker can only manage assets below it's script's directory so
// we have to put it in / instead of /js/
2020-05-23 16:58:58 +03:00
return chunk . name === 'serviceworker' ? '[name].js' : 'js/[name].js' ;
2020-05-22 04:45:34 +03:00
} ,
2020-12-27 17:24:27 +03:00
chunkFilename : ( { chunk } ) => {
const language = ( /monaco.*languages?_.+?_(.+?)_/ . exec ( chunk . id ) || [ ] ) [ 1 ] ;
2022-08-23 15:58:04 +03:00
return ` js/ ${ language ? ` monaco-language- ${ language . toLowerCase ( ) } ` : ` [name] ` } .[contenthash:8].js ` ;
2020-12-27 17:24:27 +03:00
} ,
2019-11-13 17:52:13 +03:00
} ,
optimization : {
2020-02-23 11:47:42 +03:00
minimize : isProduction ,
2020-01-25 11:41:34 +03:00
minimizer : [
2021-04-02 03:11:04 +03:00
new ESBuildMinifyPlugin ( {
target : 'es2015' ,
2021-05-07 22:12:37 +03:00
minify : true ,
css : true ,
2021-05-20 00:46:30 +03:00
legalComments : 'none' ,
2020-01-25 11:41:34 +03:00
} ) ,
] ,
2020-01-29 00:57:20 +03:00
splitChunks : {
chunks : 'async' ,
name : ( _ , chunks ) => chunks . map ( ( item ) => item . name ) . join ( '-' ) ,
2020-06-28 05:59:56 +03:00
} ,
2020-12-27 17:24:27 +03:00
moduleIds : 'named' ,
chunkIds : 'named' ,
2019-11-13 17:52:13 +03:00
} ,
2019-11-15 00:39:51 +03:00
module : {
rules : [
2020-01-20 13:07:30 +03:00
{
test : /\.vue$/ ,
exclude : /node_modules/ ,
2020-01-25 11:41:34 +03:00
loader : 'vue-loader' ,
2020-01-20 13:07:30 +03:00
} ,
2020-04-13 16:02:31 +03:00
{
test : /\.worker\.js$/ ,
2020-05-14 19:06:01 +03:00
exclude : /monaco/ ,
2020-04-13 16:02:31 +03:00
use : [
{
loader : 'worker-loader' ,
options : {
2020-08-12 01:30:47 +03:00
inline : 'no-fallback' ,
2020-04-13 16:02:31 +03:00
} ,
} ,
] ,
} ,
2019-11-15 00:39:51 +03:00
{
test : /\.js$/ ,
exclude : /node_modules/ ,
2020-01-22 09:35:29 +03:00
use : [
{
2021-04-02 03:11:04 +03:00
loader : 'esbuild-loader' ,
2020-01-22 09:35:29 +03:00
options : {
2021-04-02 03:11:04 +03:00
target : 'es2015'
2020-01-25 11:41:34 +03:00
} ,
2020-01-22 09:35:29 +03:00
} ,
] ,
2019-11-18 00:39:06 +03:00
} ,
{
2020-06-28 05:59:56 +03:00
test : /.css$/i ,
use : [
{
loader : MiniCssExtractPlugin . loader ,
} ,
{
loader : 'css-loader' ,
options : {
2020-09-10 07:16:40 +03:00
sourceMap : true ,
2021-08-17 08:32:48 +03:00
url : { filter : filterCssImport } ,
import : { filter : filterCssImport } ,
2020-06-28 05:59:56 +03:00
} ,
} ,
] ,
} ,
{
test : /.less$/i ,
2020-01-25 11:41:34 +03:00
use : [
{
loader : MiniCssExtractPlugin . loader ,
} ,
{
loader : 'css-loader' ,
options : {
2020-09-10 07:16:40 +03:00
sourceMap : true ,
2020-10-19 23:01:06 +03:00
importLoaders : 1 ,
2021-08-17 08:32:48 +03:00
url : { filter : filterCssImport } ,
import : { filter : filterCssImport } ,
2020-06-28 05:59:56 +03:00
} ,
2020-01-25 11:41:34 +03:00
} ,
2020-01-28 10:30:39 +03:00
{
loader : 'less-loader' ,
2020-06-28 05:59:56 +03:00
options : {
sourceMap : true ,
} ,
2020-01-28 10:30:39 +03:00
} ,
2020-01-25 11:41:34 +03:00
] ,
2019-11-18 00:39:06 +03:00
} ,
2020-02-11 20:02:41 +03:00
{
test : /\.svg$/ ,
2022-06-06 06:27:25 +03:00
include : fileURLToPath ( new URL ( 'public/img/svg' , import . meta . url ) ) ,
2021-03-23 01:10:09 +03:00
type : 'asset/source' ,
2020-02-11 20:02:41 +03:00
} ,
2020-05-14 19:06:01 +03:00
{
test : /\.(ttf|woff2?)$/ ,
2021-03-30 14:17:24 +03:00
type : 'asset/resource' ,
generator : {
2022-08-23 15:58:04 +03:00
filename : 'fonts/[name].[contenthash:8][ext]' ,
2021-03-30 14:17:24 +03:00
}
2020-07-29 21:44:23 +03:00
} ,
{
test : /\.png$/i ,
2021-03-30 14:17:24 +03:00
type : 'asset/resource' ,
generator : {
2022-08-23 15:58:04 +03:00
filename : 'img/webpack/[name].[contenthash:8][ext]' ,
2021-03-30 14:17:24 +03:00
}
2020-05-14 19:06:01 +03:00
} ,
2020-01-25 11:41:34 +03:00
] ,
2020-01-14 21:02:08 +03:00
} ,
plugins : [
2020-01-20 13:07:30 +03:00
new VueLoaderPlugin ( ) ,
2020-01-25 11:41:34 +03:00
new MiniCssExtractPlugin ( {
filename : 'css/[name].css' ,
2022-08-23 15:58:04 +03:00
chunkFilename : 'css/[name].[contenthash:8].css' ,
2020-01-25 11:41:34 +03:00
} ) ,
2020-01-14 21:02:08 +03:00
new SourceMapDevToolPlugin ( {
2022-08-23 15:58:04 +03:00
filename : '[file].[contenthash:8].map' ,
2020-01-29 00:57:20 +03:00
include : [
'js/index.js' ,
2020-06-28 05:59:56 +03:00
'css/index.css' ,
2020-01-14 21:02:08 +03:00
] ,
} ) ,
2020-05-14 19:06:01 +03:00
new MonacoWebpackPlugin ( {
2022-08-23 15:58:04 +03:00
filename : 'js/monaco-[name].[contenthash:8].worker.js' ,
2020-05-14 19:06:01 +03:00
} ) ,
2020-12-27 17:24:27 +03:00
isProduction ? new LicenseCheckerWebpackPlugin ( {
2020-06-12 14:26:37 +03:00
outputFilename : 'js/licenses.txt' ,
2020-12-27 17:24:27 +03:00
outputWriter : ( { dependencies } ) => {
2020-06-12 14:26:37 +03:00
const line = '-' . repeat ( 80 ) ;
2022-09-08 00:35:54 +03:00
const goJson = readFileSync ( 'assets/go-licenses.json' , 'utf8' ) ;
const goModules = JSON . parse ( goJson ) . map ( ( { name , licenseText } ) => {
return { name , body : formatLicenseText ( licenseText ) } ;
} ) ;
2022-09-04 01:20:46 +03:00
const jsModules = dependencies . map ( ( { name , version , licenseName , licenseText } ) => {
2022-09-08 00:35:54 +03:00
return { name , version , licenseName , body : formatLicenseText ( licenseText ) } ;
2022-09-04 01:20:46 +03:00
} ) ;
const modules = [ ... goModules , ... jsModules ] . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ;
return modules . map ( ( { name , version , licenseName , body } ) => {
const title = licenseName ? ` ${ name } @ ${ version } - ${ licenseName } ` : name ;
return ` ${ line } \n ${ title } \n ${ line } \n ${ body } ` ;
2020-06-12 14:26:37 +03:00
} ) . join ( '\n' ) ;
} ,
2020-12-27 17:24:27 +03:00
override : {
2022-11-22 03:58:55 +03:00
'jquery.are-you-sure@*' : { licenseName : 'MIT' } , // https://github.com/codedance/jquery.AreYouSure/pull/147
'khroma@*' : { licenseName : 'MIT' } , // https://github.com/fabiospampinato/khroma/pull/33
2020-06-12 14:26:37 +03:00
} ,
2022-11-18 20:54:32 +03:00
emitError : true ,
2022-11-22 03:58:55 +03:00
allow : '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0 OR Unlicense)' ,
2021-10-19 10:23:58 +03:00
ignore : [
'font-awesome' ,
] ,
2020-08-22 04:23:03 +03:00
} ) : new AddAssetPlugin ( 'js/licenses.txt' , ` Licenses are disabled during development ` ) ,
2020-01-14 21:02:08 +03:00
] ,
performance : {
2020-03-18 01:57:17 +03:00
hints : false ,
2020-05-14 19:06:01 +03:00
maxEntrypointSize : Infinity ,
maxAssetSize : Infinity ,
2020-01-14 21:02:08 +03:00
} ,
2020-01-22 09:35:29 +03:00
resolve : {
symlinks : false ,
2020-01-25 11:41:34 +03:00
} ,
2020-02-23 11:47:42 +03:00
watchOptions : {
ignored : [
'node_modules/**' ,
] ,
} ,
2020-05-14 19:06:01 +03:00
stats : {
2020-12-27 17:24:27 +03:00
assetsSort : 'name' ,
assetsSpace : Infinity ,
cached : false ,
cachedModules : false ,
2020-05-14 19:06:01 +03:00
children : false ,
2020-12-27 17:24:27 +03:00
chunkModules : false ,
chunkOrigins : false ,
chunksSort : 'name' ,
colors : true ,
entrypoints : false ,
2020-08-02 17:06:06 +03:00
excludeAssets : [
2020-12-27 17:24:27 +03:00
/^js\/monaco-language-.+\.js$/ ,
! isProduction && /^js\/licenses.txt$/ ,
2022-10-10 15:02:20 +03:00
] . filter ( Boolean ) ,
2020-12-27 17:24:27 +03:00
groupAssetsByChunk : false ,
groupAssetsByEmitStatus : false ,
groupAssetsByInfo : false ,
groupModulesByAttributes : false ,
modules : false ,
reasons : false ,
runtimeModules : false ,
2020-05-14 19:06:01 +03:00
} ,
2019-11-13 17:52:13 +03:00
} ;