* Update JS dependencies - Update all JS dependencies - Adapt webpack config for version 5 - Update to Less 4.0, adapting usage of removed mixin syntax - Enable new ESLint rules and fix discovered issues * update license-webpack-plugin to fix missing licenses * update license-webpack-plugin once more to get webpack into the license output * switch to license-checker-webpack-plugin again for performance * update deps again Co-authored-by: Lauris BH <lauris@nix.lv>tags/v1.15.0-dev
@@ -346,6 +346,7 @@ rules: | |||||
unicorn/catch-error-name: [0] | unicorn/catch-error-name: [0] | ||||
unicorn/consistent-function-scoping: [2] | unicorn/consistent-function-scoping: [2] | ||||
unicorn/custom-error-definition: [0] | unicorn/custom-error-definition: [0] | ||||
unicorn/empty-brace-spaces: [2] | |||||
unicorn/error-message: [0] | unicorn/error-message: [0] | ||||
unicorn/escape-case: [0] | unicorn/escape-case: [0] | ||||
unicorn/expiring-todo-comments: [0] | unicorn/expiring-todo-comments: [0] | ||||
@@ -361,6 +362,7 @@ rules: | |||||
unicorn/no-for-loop: [0] | unicorn/no-for-loop: [0] | ||||
unicorn/no-hex-escape: [0] | unicorn/no-hex-escape: [0] | ||||
unicorn/no-keyword-prefix: [0] | unicorn/no-keyword-prefix: [0] | ||||
unicorn/no-lonely-if: [2] | |||||
unicorn/no-nested-ternary: [0] | unicorn/no-nested-ternary: [0] | ||||
unicorn/no-new-buffer: [0] | unicorn/no-new-buffer: [0] | ||||
unicorn/no-null: [0] | unicorn/no-null: [0] | ||||
@@ -377,6 +379,7 @@ rules: | |||||
unicorn/prefer-add-event-listener: [2] | unicorn/prefer-add-event-listener: [2] | ||||
unicorn/prefer-array-find: [2] | unicorn/prefer-array-find: [2] | ||||
unicorn/prefer-dataset: [2] | unicorn/prefer-dataset: [2] | ||||
unicorn/prefer-date-now: [2] | |||||
unicorn/prefer-event-key: [2] | unicorn/prefer-event-key: [2] | ||||
unicorn/prefer-includes: [2] | unicorn/prefer-includes: [2] | ||||
unicorn/prefer-math-trunc: [2] | unicorn/prefer-math-trunc: [2] | ||||
@@ -317,8 +317,8 @@ lint: lint-frontend lint-backend | |||||
.PHONY: lint-frontend | .PHONY: lint-frontend | ||||
lint-frontend: node_modules | lint-frontend: node_modules | ||||
npx eslint --max-warnings=0 web_src/js build templates webpack.config.js | |||||
npx stylelint --max-warnings=0 web_src/less | |||||
npx eslint --color --max-warnings=0 web_src/js build templates webpack.config.js | |||||
npx stylelint --color --max-warnings=0 web_src/less | |||||
.PHONY: lint-backend | .PHONY: lint-backend | ||||
lint-backend: golangci-lint revive vet | lint-backend: golangci-lint revive vet | ||||
@@ -330,7 +330,7 @@ watch: | |||||
.PHONY: watch-frontend | .PHONY: watch-frontend | ||||
watch-frontend: node-check node_modules | watch-frontend: node-check node_modules | ||||
rm -rf $(WEBPACK_DEST_ENTRIES) | rm -rf $(WEBPACK_DEST_ENTRIES) | ||||
NODE_ENV=development npx webpack --hide-modules --display-entrypoints=false --watch --progress | |||||
NODE_ENV=development npx webpack --watch --progress | |||||
.PHONY: watch-backend | .PHONY: watch-backend | ||||
watch-backend: go-check | watch-backend: go-check | ||||
@@ -660,7 +660,7 @@ webpack: $(WEBPACK_DEST) | |||||
$(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json | node_modules | $(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json | node_modules | ||||
rm -rf $(WEBPACK_DEST_ENTRIES) | rm -rf $(WEBPACK_DEST_ENTRIES) | ||||
npx webpack --hide-modules --display-entrypoints=false | |||||
npx webpack | |||||
@touch $(WEBPACK_DEST) | @touch $(WEBPACK_DEST) | ||||
.PHONY: svg | .PHONY: svg | ||||
@@ -5,17 +5,17 @@ | |||||
"node": ">= 10.13.0" | "node": ">= 10.13.0" | ||||
}, | }, | ||||
"dependencies": { | "dependencies": { | ||||
"@babel/core": "7.12.9", | |||||
"@babel/plugin-transform-runtime": "7.12.1", | |||||
"@babel/preset-env": "7.12.7", | |||||
"@babel/core": "7.12.10", | |||||
"@babel/plugin-transform-runtime": "7.12.10", | |||||
"@babel/preset-env": "7.12.11", | |||||
"@babel/runtime": "7.12.5", | "@babel/runtime": "7.12.5", | ||||
"@claviska/jquery-minicolors": "2.3.5", | "@claviska/jquery-minicolors": "2.3.5", | ||||
"@primer/octicons": "11.1.0", | |||||
"add-asset-webpack-plugin": "1.0.0", | |||||
"@primer/octicons": "11.2.0", | |||||
"add-asset-webpack-plugin": "2.0.0", | |||||
"babel-loader": "8.2.2", | "babel-loader": "8.2.2", | ||||
"clipboard": "2.0.6", | "clipboard": "2.0.6", | ||||
"codemirror": "5.58.3", | |||||
"core-js": "3.8.0", | |||||
"codemirror": "5.59.0", | |||||
"core-js": "3.8.1", | |||||
"css-loader": "5.0.1", | "css-loader": "5.0.1", | ||||
"css-minimizer-webpack-plugin": "1.1.5", | "css-minimizer-webpack-plugin": "1.1.5", | ||||
"dropzone": "5.7.2", | "dropzone": "5.7.2", | ||||
@@ -26,42 +26,41 @@ | |||||
"font-awesome": "4.7.0", | "font-awesome": "4.7.0", | ||||
"jquery": "3.5.1", | "jquery": "3.5.1", | ||||
"jquery.are-you-sure": "1.9.0", | "jquery.are-you-sure": "1.9.0", | ||||
"less": "3.12.2", | |||||
"less-loader": "7.1.0", | |||||
"license-webpack-plugin": "2.3.1", | |||||
"mermaid": "8.8.3", | |||||
"mini-css-extract-plugin": "1.3.1", | |||||
"less": "4.0.0", | |||||
"less-loader": "7.2.0", | |||||
"license-checker-webpack-plugin": "0.2.1", | |||||
"mermaid": "8.8.4", | |||||
"mini-css-extract-plugin": "1.3.3", | |||||
"monaco-editor": "0.21.2", | "monaco-editor": "0.21.2", | ||||
"monaco-editor-webpack-plugin": "2.0.0", | |||||
"postcss": "8.1.10", | |||||
"monaco-editor-webpack-plugin": "2.1.0", | |||||
"postcss": "8.2.1", | |||||
"raw-loader": "4.0.2", | "raw-loader": "4.0.2", | ||||
"sortablejs": "1.12.0", | "sortablejs": "1.12.0", | ||||
"swagger-ui-dist": "3.37.2", | |||||
"terser-webpack-plugin": "4.2.3", | |||||
"swagger-ui-dist": "3.38.0", | |||||
"terser-webpack-plugin": "5.0.3", | |||||
"tributejs": "5.1.3", | "tributejs": "5.1.3", | ||||
"vue": "2.6.12", | "vue": "2.6.12", | ||||
"vue-bar-graph": "1.2.0", | "vue-bar-graph": "1.2.0", | ||||
"vue-calendar-heatmap": "0.8.4", | "vue-calendar-heatmap": "0.8.4", | ||||
"vue-loader": "15.9.5", | |||||
"vue-loader": "15.9.6", | |||||
"vue-template-compiler": "2.6.12", | "vue-template-compiler": "2.6.12", | ||||
"webpack": "4.44.1", | |||||
"webpack-cli": "3.3.12", | |||||
"webpack-fix-style-only-entries": "0.6.0", | |||||
"workbox-routing": "5.1.4", | |||||
"workbox-strategies": "5.1.4", | |||||
"worker-loader": "3.0.5", | |||||
"webpack": "5.11.0", | |||||
"webpack-cli": "4.3.0", | |||||
"workbox-routing": "6.0.2", | |||||
"workbox-strategies": "6.0.2", | |||||
"worker-loader": "3.0.7", | |||||
"wrap-ansi": "7.0.0" | "wrap-ansi": "7.0.0" | ||||
}, | }, | ||||
"devDependencies": { | "devDependencies": { | ||||
"eslint": "7.14.0", | |||||
"eslint": "7.16.0", | |||||
"eslint-plugin-html": "6.1.1", | "eslint-plugin-html": "6.1.1", | ||||
"eslint-plugin-import": "2.22.1", | "eslint-plugin-import": "2.22.1", | ||||
"eslint-plugin-unicorn": "23.0.0", | |||||
"eslint-plugin-vue": "7.1.0", | |||||
"eslint-plugin-unicorn": "24.0.0", | |||||
"eslint-plugin-vue": "7.3.0", | |||||
"stylelint": "13.8.0", | "stylelint": "13.8.0", | ||||
"stylelint-config-standard": "20.0.0", | "stylelint-config-standard": "20.0.0", | ||||
"svgo": "1.3.2", | "svgo": "1.3.2", | ||||
"updates": "11.4.0" | |||||
"updates": "11.4.2" | |||||
}, | }, | ||||
"browserslist": [ | "browserslist": [ | ||||
"defaults", | "defaults", | ||||
@@ -1 +1 @@ | |||||
<svg viewBox="0 0 16 16" class="svg octicon-dash" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M2 8a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H2.75A.75.75 0 012 8z"/></svg> | |||||
<svg viewBox="0 0 16 16" class="svg octicon-dash" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M2 7.75A.75.75 0 012.75 7h10a.75.75 0 010 1.5h-10A.75.75 0 012 7.75z"/></svg> |
@@ -1 +1 @@ | |||||
<svg viewBox="0 0 16 16" class="svg octicon-plus" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 2a.75.75 0 01.75.75v4.5h4.5a.75.75 0 010 1.5h-4.5v4.5a.75.75 0 01-1.5 0v-4.5h-4.5a.75.75 0 010-1.5h4.5v-4.5A.75.75 0 018 2z"/></svg> | |||||
<svg viewBox="0 0 16 16" class="svg octicon-plus" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.75 2a.75.75 0 01.75.75V7h4.25a.75.75 0 110 1.5H8.5v4.25a.75.75 0 11-1.5 0V8.5H2.75a.75.75 0 010-1.5H7V2.75A.75.75 0 017.75 2z"/></svg> |
@@ -0,0 +1 @@ | |||||
<svg viewBox="0 0 16 16" class="svg octicon-strikethrough" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.581 3.25c-2.036 0-2.778 1.082-2.778 1.786 0 .055.002.107.006.157a.75.75 0 01-1.496.114 3.56 3.56 0 01-.01-.271c0-1.832 1.75-3.286 4.278-3.286 1.418 0 2.721.58 3.514 1.093a.75.75 0 11-.814 1.26c-.64-.414-1.662-.853-2.7-.853zm3.474 5.25h3.195a.75.75 0 000-1.5H1.75a.75.75 0 000 1.5h6.018c.835.187 1.503.464 1.951.81.439.34.647.725.647 1.197 0 .428-.159.895-.594 1.267-.444.38-1.254.726-2.676.726-1.373 0-2.38-.493-2.86-.956a.75.75 0 00-1.042 1.079C3.992 13.393 5.39 14 7.096 14c1.652 0 2.852-.403 3.65-1.085a3.134 3.134 0 001.12-2.408 2.85 2.85 0 00-.811-2.007z"/></svg> |
@@ -43,53 +43,51 @@ export async function initNotificationCount() { | |||||
return; | return; | ||||
} | } | ||||
if (NotificationSettings.EventSourceUpdateTime > 0 && !!window.EventSource) { | |||||
if (NotificationSettings.EventSourceUpdateTime > 0 && !!window.EventSource && window.SharedWorker) { | |||||
// Try to connect to the event source via the shared worker first | // Try to connect to the event source via the shared worker first | ||||
if (window.SharedWorker) { | |||||
const worker = new SharedWorker(`${__webpack_public_path__}js/eventsource.sharedworker.js`, 'notification-worker'); | |||||
worker.addEventListener('error', (event) => { | |||||
const worker = new SharedWorker(`${__webpack_public_path__}js/eventsource.sharedworker.js`, 'notification-worker'); | |||||
worker.addEventListener('error', (event) => { | |||||
console.error(event); | |||||
}); | |||||
worker.port.onmessageerror = () => { | |||||
console.error('Unable to deserialize message'); | |||||
}; | |||||
worker.port.postMessage({ | |||||
type: 'start', | |||||
url: `${window.location.origin}${AppSubUrl}/user/events`, | |||||
}); | |||||
worker.port.addEventListener('message', (event) => { | |||||
if (!event.data || !event.data.type) { | |||||
console.error(event); | console.error(event); | ||||
}); | |||||
worker.port.onmessageerror = () => { | |||||
console.error('Unable to deserialize message'); | |||||
}; | |||||
worker.port.postMessage({ | |||||
type: 'start', | |||||
url: `${window.location.origin}${AppSubUrl}/user/events`, | |||||
}); | |||||
worker.port.addEventListener('message', (event) => { | |||||
if (!event.data || !event.data.type) { | |||||
console.error(event); | |||||
return; | |||||
} | |||||
if (event.data.type === 'notification-count') { | |||||
receiveUpdateCount(event.data); | |||||
} else if (event.data.type === 'error') { | |||||
console.error(event.data); | |||||
} else if (event.data.type === 'logout') { | |||||
if (event.data !== 'here') { | |||||
return; | return; | ||||
} | } | ||||
if (event.data.type === 'notification-count') { | |||||
receiveUpdateCount(event.data); | |||||
} else if (event.data.type === 'error') { | |||||
console.error(event.data); | |||||
} else if (event.data.type === 'logout') { | |||||
if (event.data !== 'here') { | |||||
return; | |||||
} | |||||
worker.port.postMessage({ | |||||
type: 'close', | |||||
}); | |||||
worker.port.close(); | |||||
window.location.href = AppSubUrl; | |||||
} | |||||
}); | |||||
worker.port.addEventListener('error', (e) => { | |||||
console.error(e); | |||||
}); | |||||
worker.port.start(); | |||||
window.addEventListener('beforeunload', () => { | |||||
worker.port.postMessage({ | worker.port.postMessage({ | ||||
type: 'close', | type: 'close', | ||||
}); | }); | ||||
worker.port.close(); | worker.port.close(); | ||||
window.location.href = AppSubUrl; | |||||
} | |||||
}); | |||||
worker.port.addEventListener('error', (e) => { | |||||
console.error(e); | |||||
}); | |||||
worker.port.start(); | |||||
window.addEventListener('beforeunload', () => { | |||||
worker.port.postMessage({ | |||||
type: 'close', | |||||
}); | }); | ||||
worker.port.close(); | |||||
}); | |||||
return; | |||||
} | |||||
return; | |||||
} | } | ||||
if (NotificationSettings.MinTimeout <= 0) { | if (NotificationSettings.MinTimeout <= 0) { | ||||
@@ -204,24 +204,22 @@ function initRepoStatusChecker() { | |||||
_csrf: csrf, | _csrf: csrf, | ||||
}, | }, | ||||
complete(xhr) { | complete(xhr) { | ||||
if (xhr.status === 200) { | |||||
if (xhr.responseJSON) { | |||||
if (xhr.responseJSON.status === 4) { | |||||
window.location.reload(); | |||||
return; | |||||
} else if (xhr.responseJSON.status === 3) { | |||||
$('#repo_migrating_progress').hide(); | |||||
$('#repo_migrating').hide(); | |||||
$('#repo_migrating_failed').show(); | |||||
$('#repo_migrating_failed_image').show(); | |||||
$('#repo_migrating_failed_error').text(xhr.responseJSON.err); | |||||
return; | |||||
} | |||||
setTimeout(() => { | |||||
initRepoStatusChecker(); | |||||
}, 2000); | |||||
if (xhr.status === 200 && xhr.responseJSON) { | |||||
if (xhr.responseJSON.status === 4) { | |||||
window.location.reload(); | |||||
return; | |||||
} else if (xhr.responseJSON.status === 3) { | |||||
$('#repo_migrating_progress').hide(); | |||||
$('#repo_migrating').hide(); | |||||
$('#repo_migrating_failed').show(); | |||||
$('#repo_migrating_failed_image').show(); | |||||
$('#repo_migrating_failed_error').text(xhr.responseJSON.err); | |||||
return; | return; | ||||
} | } | ||||
setTimeout(() => { | |||||
initRepoStatusChecker(); | |||||
}, 2000); | |||||
return; | |||||
} | } | ||||
$('#repo_migrating_progress').hide(); | $('#repo_migrating_progress').hide(); | ||||
$('#repo_migrating').hide(); | $('#repo_migrating').hide(); | ||||
@@ -1625,16 +1623,12 @@ async function initEditor() { | |||||
let value; | let value; | ||||
let parts; | let parts; | ||||
if (e.keyCode === 8) { | |||||
if ($(this).getCursorPosition() === 0) { | |||||
if ($section.length > 0) { | |||||
value = $section.last().find('a').text(); | |||||
$(this).val(value + $(this).val()); | |||||
$(this)[0].setSelectionRange(value.length, value.length); | |||||
$section.last().remove(); | |||||
$divider.last().remove(); | |||||
} | |||||
} | |||||
if (e.keyCode === 8 && $(this).getCursorPosition() === 0 && $section.length > 0) { | |||||
value = $section.last().find('a').text(); | |||||
$(this).val(value + $(this).val()); | |||||
$(this)[0].setSelectionRange(value.length, value.length); | |||||
$section.last().remove(); | |||||
$divider.last().remove(); | |||||
} | } | ||||
if (e.keyCode === 191) { | if (e.keyCode === 191) { | ||||
parts = $(this).val().split('/'); | parts = $(this).val().split('/'); | ||||
@@ -236,7 +236,7 @@ textarea:focus, | |||||
.user.signin, | .user.signin, | ||||
.user.signup { | .user.signup { | ||||
@input-padding: 200px; | @input-padding: 200px; | ||||
#create-page-form; | |||||
#create-page-form(); | |||||
form { | form { | ||||
width: 700px !important; | width: 700px !important; | ||||
@@ -273,7 +273,7 @@ textarea:focus, | |||||
&.new.repo, | &.new.repo, | ||||
&.new.migrate, | &.new.migrate, | ||||
&.new.fork { | &.new.fork { | ||||
#create-page-form; | |||||
#create-page-form(); | |||||
form { | form { | ||||
.dropdown .text { | .dropdown .text { | ||||
@@ -17,7 +17,7 @@ | |||||
} | } | ||||
&.new.org { | &.new.org { | ||||
#create-page-form; | |||||
#create-page-form(); | |||||
form { | form { | ||||
.header { | .header { | ||||
@@ -484,7 +484,7 @@ | |||||
border: 1px solid var(--color-secondary); | border: 1px solid var(--color-secondary); | ||||
background: var(--color-box-body); | background: var(--color-box-body); | ||||
border-radius: 3px; | border-radius: 3px; | ||||
#avatar-arrow; | |||||
#avatar-arrow(); | |||||
&::after { | &::after { | ||||
border-right-color: var(--color-box-body); | border-right-color: var(--color-box-body); | ||||
@@ -555,7 +555,7 @@ | |||||
.content { | .content { | ||||
margin-left: 4em; | margin-left: 4em; | ||||
#avatar-arrow; | |||||
#avatar-arrow(); | |||||
&::after { | &::after { | ||||
border-right-color: var(--color-box-body); | border-right-color: var(--color-box-body); | ||||
@@ -979,7 +979,7 @@ | |||||
} | } | ||||
&.no-header { | &.no-header { | ||||
#avatar-arrow; | |||||
#avatar-arrow(); | |||||
&::after { | &::after { | ||||
border-right-color: var(--color-box-body); | border-right-color: var(--color-box-body); | ||||
@@ -1098,7 +1098,7 @@ | |||||
} | } | ||||
.form { | .form { | ||||
#avatar-arrow; | |||||
#avatar-arrow(); | |||||
&::after { | &::after { | ||||
border-right-color: var(--color-box-body); | border-right-color: var(--color-box-body); | ||||
@@ -1195,7 +1195,7 @@ | |||||
.comment.form { | .comment.form { | ||||
.content { | .content { | ||||
#avatar-arrow; | |||||
#avatar-arrow(); | |||||
&::after { | &::after { | ||||
border-right-color: var(--color-box-body); | border-right-color: var(--color-box-body); | ||||
@@ -2458,7 +2458,7 @@ | |||||
} | } | ||||
.comment-header { | .comment-header { | ||||
#avatar-arrow; | |||||
#avatar-arrow(); | |||||
border: none !important; | border: none !important; | ||||
background: var(--color-box-header); | background: var(--color-box-header); | ||||
border-bottom: 1px solid var(--color-secondary) !important; | border-bottom: 1px solid var(--color-secondary) !important; | ||||
@@ -2,14 +2,13 @@ const fastGlob = require('fast-glob'); | |||||
const wrapAnsi = require('wrap-ansi'); | const wrapAnsi = require('wrap-ansi'); | ||||
const AddAssetPlugin = require('add-asset-webpack-plugin'); | const AddAssetPlugin = require('add-asset-webpack-plugin'); | ||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); | const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); | ||||
const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries'); | |||||
const LicenseCheckerWebpackPlugin = require('license-checker-webpack-plugin'); | |||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||||
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); | const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); | ||||
const TerserPlugin = require('terser-webpack-plugin'); | const TerserPlugin = require('terser-webpack-plugin'); | ||||
const VueLoaderPlugin = require('vue-loader/lib/plugin'); | const VueLoaderPlugin = require('vue-loader/lib/plugin'); | ||||
const {statSync} = require('fs'); | const {statSync} = require('fs'); | ||||
const {resolve, parse} = require('path'); | const {resolve, parse} = require('path'); | ||||
const {LicenseWebpackPlugin} = require('license-webpack-plugin'); | |||||
const {SourceMapDevToolPlugin} = require('webpack'); | const {SourceMapDevToolPlugin} = require('webpack'); | ||||
const glob = (pattern) => fastGlob.sync(pattern, {cwd: __dirname, absolute: true}); | const glob = (pattern) => fastGlob.sync(pattern, {cwd: __dirname, absolute: true}); | ||||
@@ -30,8 +29,8 @@ const filterCssImport = (url, ...args) => { | |||||
if (/(eot|ttf|otf|woff|svg)$/.test(importedFile)) return false; | if (/(eot|ttf|otf|woff|svg)$/.test(importedFile)) return false; | ||||
} | } | ||||
if (cssFile.includes('font-awesome')) { | |||||
if (/(eot|ttf|otf|woff|svg)$/.test(importedFile)) return false; | |||||
if (cssFile.includes('font-awesome') && /(eot|ttf|otf|woff|svg)$/.test(importedFile)) { | |||||
return false; | |||||
} | } | ||||
return true; | return true; | ||||
@@ -71,13 +70,15 @@ module.exports = { | |||||
// we have to put it in / instead of /js/ | // we have to put it in / instead of /js/ | ||||
return chunk.name === 'serviceworker' ? '[name].js' : 'js/[name].js'; | return chunk.name === 'serviceworker' ? '[name].js' : 'js/[name].js'; | ||||
}, | }, | ||||
chunkFilename: 'js/[name].js', | |||||
chunkFilename: ({chunk}) => { | |||||
const language = (/monaco.*languages?_.+?_(.+?)_/.exec(chunk.id) || [])[1]; | |||||
return language ? `js/monaco-language-${language.toLowerCase()}.js` : `js/[name].js`; | |||||
}, | |||||
}, | }, | ||||
optimization: { | optimization: { | ||||
minimize: isProduction, | minimize: isProduction, | ||||
minimizer: [ | minimizer: [ | ||||
new TerserPlugin({ | new TerserPlugin({ | ||||
sourceMap: true, | |||||
extractComments: false, | extractComments: false, | ||||
terserOptions: { | terserOptions: { | ||||
output: { | output: { | ||||
@@ -103,6 +104,8 @@ module.exports = { | |||||
chunks: 'async', | chunks: 'async', | ||||
name: (_, chunks) => chunks.map((item) => item.name).join('-'), | name: (_, chunks) => chunks.map((item) => item.name).join('-'), | ||||
}, | }, | ||||
moduleIds: 'named', | |||||
chunkIds: 'named', | |||||
}, | }, | ||||
module: { | module: { | ||||
rules: [ | rules: [ | ||||
@@ -240,11 +243,6 @@ module.exports = { | |||||
}, | }, | ||||
plugins: [ | plugins: [ | ||||
new VueLoaderPlugin(), | new VueLoaderPlugin(), | ||||
// avoid generating useless js output files for css--only chunks | |||||
new FixStyleOnlyEntriesPlugin({ | |||||
extensions: ['less', 'scss', 'css'], | |||||
silent: true, | |||||
}), | |||||
new MiniCssExtractPlugin({ | new MiniCssExtractPlugin({ | ||||
filename: 'css/[name].css', | filename: 'css/[name].css', | ||||
chunkFilename: 'css/[name].css', | chunkFilename: 'css/[name].css', | ||||
@@ -259,29 +257,18 @@ module.exports = { | |||||
new MonacoWebpackPlugin({ | new MonacoWebpackPlugin({ | ||||
filename: 'js/monaco-[name].worker.js', | filename: 'js/monaco-[name].worker.js', | ||||
}), | }), | ||||
isProduction ? new LicenseWebpackPlugin({ | |||||
isProduction ? new LicenseCheckerWebpackPlugin({ | |||||
outputFilename: 'js/licenses.txt', | outputFilename: 'js/licenses.txt', | ||||
perChunkOutput: false, | |||||
addBanner: false, | |||||
skipChildCompilers: true, | |||||
modulesDirectories: [ | |||||
resolve(__dirname, 'node_modules'), | |||||
], | |||||
additionalModules: [ | |||||
'@primer/octicons', | |||||
].map((name) => ({name, directory: resolve(__dirname, `node_modules/${name}`)})), | |||||
renderLicenses: (modules) => { | |||||
outputWriter: ({dependencies}) => { | |||||
const line = '-'.repeat(80); | const line = '-'.repeat(80); | ||||
return modules.map((module) => { | |||||
const {name, version} = module.packageJson; | |||||
const {licenseId, licenseText} = module; | |||||
return dependencies.map((module) => { | |||||
const {name, version, licenseName, licenseText} = module; | |||||
const body = wrapAnsi(licenseText || '', 80); | const body = wrapAnsi(licenseText || '', 80); | ||||
return `${line}\n${name}@${version} - ${licenseId}\n${line}\n${body}`; | |||||
return `${line}\n${name}@${version} - ${licenseName}\n${line}\n${body}`; | |||||
}).join('\n'); | }).join('\n'); | ||||
}, | }, | ||||
stats: { | |||||
warnings: false, | |||||
errors: true, | |||||
override: { | |||||
'jquery.are-you-sure@*': {licenseName: 'MIT'}, | |||||
}, | }, | ||||
}) : new AddAssetPlugin('js/licenses.txt', `Licenses are disabled during development`), | }) : new AddAssetPlugin('js/licenses.txt', `Licenses are disabled during development`), | ||||
], | ], | ||||
@@ -302,11 +289,26 @@ module.exports = { | |||||
], | ], | ||||
}, | }, | ||||
stats: { | stats: { | ||||
assetsSort: 'name', | |||||
assetsSpace: Infinity, | |||||
cached: false, | |||||
cachedModules: false, | |||||
children: false, | children: false, | ||||
chunkModules: false, | |||||
chunkOrigins: false, | |||||
chunksSort: 'name', | |||||
colors: true, | |||||
entrypoints: false, | |||||
excludeAssets: [ | excludeAssets: [ | ||||
// exclude monaco's language chunks in stats output for brevity | |||||
// https://github.com/microsoft/monaco-editor-webpack-plugin/issues/113 | |||||
/^js\/[0-9]+\.js$/, | |||||
], | |||||
/^js\/monaco-language-.+\.js$/, | |||||
!isProduction && /^js\/licenses.txt$/, | |||||
].filter((item) => !!item), | |||||
groupAssetsByChunk: false, | |||||
groupAssetsByEmitStatus: false, | |||||
groupAssetsByInfo: false, | |||||
groupModulesByAttributes: false, | |||||
modules: false, | |||||
reasons: false, | |||||
runtimeModules: false, | |||||
}, | }, | ||||
}; | }; |