mirror of
https://github.com/gchq/CyberChef
synced 2025-12-05 23:53:27 +00:00
Compare commits
10 Commits
feature/de
...
bug/disabl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3ee16f38b | ||
|
|
e1d3af26da | ||
|
|
9d014aeaa5 | ||
|
|
156de53dc1 | ||
|
|
7ecc235b31 | ||
|
|
51ed3b2fc1 | ||
|
|
306e29da76 | ||
|
|
304266020d | ||
|
|
748379f0b0 | ||
|
|
da74d9b22d |
22
package-lock.json
generated
22
package-lock.json
generated
@@ -118,6 +118,7 @@
|
|||||||
"chromedriver": "^130.0.0",
|
"chromedriver": "^130.0.0",
|
||||||
"cli-progress": "^3.12.0",
|
"cli-progress": "^3.12.0",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
|
"compression-webpack-plugin": "^11.1.0",
|
||||||
"copy-webpack-plugin": "^12.0.2",
|
"copy-webpack-plugin": "^12.0.2",
|
||||||
"core-js": "^3.37.1",
|
"core-js": "^3.37.1",
|
||||||
"css-loader": "7.1.2",
|
"css-loader": "7.1.2",
|
||||||
@@ -5344,6 +5345,27 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/compression-webpack-plugin": {
|
||||||
|
"version": "11.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-11.1.0.tgz",
|
||||||
|
"integrity": "sha512-zDOQYp10+upzLxW+VRSjEpRRwBXJdsb5lBMlRxx1g8hckIFBpe3DTI0en2w7h+beuq89576RVzfiXrkdPGrHhA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"schema-utils": "^4.2.0",
|
||||||
|
"serialize-javascript": "^6.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18.12.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/webpack"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"webpack": "^5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/compression/node_modules/bytes": {
|
"node_modules/compression/node_modules/bytes": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
"chromedriver": "^130.0.0",
|
"chromedriver": "^130.0.0",
|
||||||
"cli-progress": "^3.12.0",
|
"cli-progress": "^3.12.0",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
|
"compression-webpack-plugin": "^11.1.0",
|
||||||
"copy-webpack-plugin": "^12.0.2",
|
"copy-webpack-plugin": "^12.0.2",
|
||||||
"core-js": "^3.37.1",
|
"core-js": "^3.37.1",
|
||||||
"css-loader": "7.1.2",
|
"css-loader": "7.1.2",
|
||||||
|
|||||||
@@ -236,8 +236,10 @@
|
|||||||
"Parse IPv6 address",
|
"Parse IPv6 address",
|
||||||
"Parse IPv4 header",
|
"Parse IPv4 header",
|
||||||
"Parse TCP",
|
"Parse TCP",
|
||||||
|
"Strip TCP header",
|
||||||
"Parse TLS record",
|
"Parse TLS record",
|
||||||
"Parse UDP",
|
"Parse UDP",
|
||||||
|
"Strip UDP header",
|
||||||
"Parse SSH Host Key",
|
"Parse SSH Host Key",
|
||||||
"Parse URI",
|
"Parse URI",
|
||||||
"URL Encode",
|
"URL Encode",
|
||||||
|
|||||||
60
src/core/operations/StripTCPHeader.mjs
Normal file
60
src/core/operations/StripTCPHeader.mjs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* @author c65722 []
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Stream from "../lib/Stream.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strip TCP header operation
|
||||||
|
*/
|
||||||
|
class StripTCPHeader extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StripTCPHeader constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Strip TCP header";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Strips the TCP header from a TCP segment, outputting the payload.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Transmission_Control_Protocol";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const MIN_HEADER_LEN = 20;
|
||||||
|
const DATA_OFFSET_OFFSET = 12;
|
||||||
|
const DATA_OFFSET_LEN_BITS = 4;
|
||||||
|
|
||||||
|
const s = new Stream(new Uint8Array(input));
|
||||||
|
if (s.length < MIN_HEADER_LEN) {
|
||||||
|
throw new OperationError("Need at least 20 bytes for a TCP Header");
|
||||||
|
}
|
||||||
|
|
||||||
|
s.moveTo(DATA_OFFSET_OFFSET);
|
||||||
|
const dataOffsetWords = s.readBits(DATA_OFFSET_LEN_BITS);
|
||||||
|
const dataOffsetBytes = dataOffsetWords * 4;
|
||||||
|
if (s.length < dataOffsetBytes) {
|
||||||
|
throw new OperationError("Input length is less than data offset");
|
||||||
|
}
|
||||||
|
|
||||||
|
s.moveTo(dataOffsetBytes);
|
||||||
|
|
||||||
|
return s.getBytes().buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StripTCPHeader;
|
||||||
51
src/core/operations/StripUDPHeader.mjs
Normal file
51
src/core/operations/StripUDPHeader.mjs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* @author c65722 []
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Stream from "../lib/Stream.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strip UDP header operation
|
||||||
|
*/
|
||||||
|
class StripUDPHeader extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StripUDPHeader constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Strip UDP header";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Strips the UDP header from a UDP datagram, outputting the payload.";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/User_Datagram_Protocol";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "ArrayBuffer";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {ArrayBuffer}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const HEADER_LEN = 8;
|
||||||
|
|
||||||
|
const s = new Stream(new Uint8Array(input));
|
||||||
|
if (s.length < HEADER_LEN) {
|
||||||
|
throw new OperationError("Need 8 bytes for a UDP Header");
|
||||||
|
}
|
||||||
|
|
||||||
|
s.moveTo(HEADER_LEN);
|
||||||
|
|
||||||
|
return s.getBytes().buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StripUDPHeader;
|
||||||
@@ -675,42 +675,42 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"Loading from URL": browser => {
|
// "Loading from URL": browser => {
|
||||||
utils.clear(browser);
|
// utils.clear(browser);
|
||||||
|
|
||||||
/* Side panel displays correct info */
|
// /* Side panel displays correct info */
|
||||||
utils.uploadFile(browser, "files/TowelDay.jpeg");
|
// utils.uploadFile(browser, "files/TowelDay.jpeg");
|
||||||
|
|
||||||
browser
|
// browser
|
||||||
.waitForElementVisible("#input-text .cm-file-details")
|
// .waitForElementVisible("#input-text .cm-file-details")
|
||||||
.waitForElementVisible("#input-text .cm-file-details .file-details-toggle-shown")
|
// .waitForElementVisible("#input-text .cm-file-details .file-details-toggle-shown")
|
||||||
.waitForElementVisible("#input-text .cm-file-details .file-details-thumbnail")
|
// .waitForElementVisible("#input-text .cm-file-details .file-details-thumbnail")
|
||||||
.waitForElementVisible("#input-text .cm-file-details .file-details-name")
|
// .waitForElementVisible("#input-text .cm-file-details .file-details-name")
|
||||||
.waitForElementVisible("#input-text .cm-file-details .file-details-size")
|
// .waitForElementVisible("#input-text .cm-file-details .file-details-size")
|
||||||
.waitForElementVisible("#input-text .cm-file-details .file-details-type")
|
// .waitForElementVisible("#input-text .cm-file-details .file-details-type")
|
||||||
.waitForElementVisible("#input-text .cm-file-details .file-details-loaded");
|
// .waitForElementVisible("#input-text .cm-file-details .file-details-loaded");
|
||||||
|
|
||||||
/* Complex deep link populates the input correctly (encoding, eol, input) */
|
// /* Complex deep link populates the input correctly (encoding, eol, input) */
|
||||||
browser
|
// browser
|
||||||
.urlHash("recipe=To_Base64('A-Za-z0-9%2B/%3D')&input=VGhlIHNoaXBzIGh1bmcgaW4gdGhlIHNreSBpbiBtdWNoIHRoZSBzYW1lIHdheSB0aGF0IGJyaWNrcyBkb24ndC4M&ienc=21866&oenc=1201&ieol=FF&oeol=PS")
|
// .urlHash("recipe=To_Base64('A-Za-z0-9%2B/%3D')&input=VGhlIHNoaXBzIGh1bmcgaW4gdGhlIHNreSBpbiBtdWNoIHRoZSBzYW1lIHdheSB0aGF0IGJyaWNrcyBkb24ndC4M&ienc=21866&oenc=1201&ieol=FF&oeol=PS")
|
||||||
.waitForElementVisible("#rec-list li.operation");
|
// .waitForElementVisible("#rec-list li.operation");
|
||||||
|
|
||||||
browser.expect.element(`#input-text .cm-content`).to.have.property("textContent").match(/^.{65}$/);
|
// browser.expect.element(`#input-text .cm-content`).to.have.property("textContent").match(/^.{65}$/);
|
||||||
browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("66");
|
// browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("66");
|
||||||
browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2");
|
// browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2");
|
||||||
|
|
||||||
browser.expect.element("#input-text .chr-enc-value").text.that.equals("KOI8-U Ukrainian Cyrillic");
|
// browser.expect.element("#input-text .chr-enc-value").text.that.equals("KOI8-U Ukrainian Cyrillic");
|
||||||
browser.expect.element("#output-text .chr-enc-value").text.that.equals("UTF-16BE");
|
// browser.expect.element("#output-text .chr-enc-value").text.that.equals("UTF-16BE");
|
||||||
|
|
||||||
browser.expect.element("#input-text .eol-value").text.that.equals("FF");
|
// browser.expect.element("#input-text .eol-value").text.that.equals("FF");
|
||||||
browser.expect.element("#output-text .eol-value").text.that.equals("PS");
|
// browser.expect.element("#output-text .eol-value").text.that.equals("PS");
|
||||||
|
|
||||||
utils.bake(browser);
|
// utils.bake(browser);
|
||||||
|
|
||||||
browser.expect.element(`#output-text .cm-content`).to.have.property("textContent").match(/^.{44}$/);
|
// browser.expect.element(`#output-text .cm-content`).to.have.property("textContent").match(/^.{44}$/);
|
||||||
browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("44");
|
// browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("44");
|
||||||
browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("1");
|
// browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("1");
|
||||||
},
|
// },
|
||||||
|
|
||||||
"Replace input with output": browser => {
|
"Replace input with output": browser => {
|
||||||
/* Input is correctly populated */
|
/* Input is correctly populated */
|
||||||
|
|||||||
@@ -143,6 +143,8 @@ import "./tests/SIGABA.mjs";
|
|||||||
import "./tests/SM4.mjs";
|
import "./tests/SM4.mjs";
|
||||||
// import "./tests/SplitColourChannels.mjs"; // Cannot test operations that use the File type yet
|
// import "./tests/SplitColourChannels.mjs"; // Cannot test operations that use the File type yet
|
||||||
import "./tests/StrUtils.mjs";
|
import "./tests/StrUtils.mjs";
|
||||||
|
import "./tests/StripTCPHeader.mjs";
|
||||||
|
import "./tests/StripUDPHeader.mjs";
|
||||||
import "./tests/Subsection.mjs";
|
import "./tests/Subsection.mjs";
|
||||||
import "./tests/SwapCase.mjs";
|
import "./tests/SwapCase.mjs";
|
||||||
import "./tests/SymmetricDifference.mjs";
|
import "./tests/SymmetricDifference.mjs";
|
||||||
|
|||||||
126
tests/operations/tests/StripTCPHeader.mjs
Normal file
126
tests/operations/tests/StripTCPHeader.mjs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/**
|
||||||
|
* Strip TCP header tests.
|
||||||
|
*
|
||||||
|
* @author c65722 []
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Strip TCP header: No options, No payload",
|
||||||
|
input: "7f900050000fa4b2000cb2a45010bff100000000",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hex",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Strip TCP header",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "To Hex",
|
||||||
|
args: ["None", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Strip TCP header: No options, Payload",
|
||||||
|
input: "7f900050000fa4b2000cb2a45010bff100000000ffffffffffffffff",
|
||||||
|
expectedOutput: "ffffffffffffffff",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hex",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Strip TCP header",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "To Hex",
|
||||||
|
args: ["None", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Strip TCP header: Options, No payload",
|
||||||
|
input: "7f900050000fa4b2000cb2a47010bff100000000020405b404020000",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hex",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Strip TCP header",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "To Hex",
|
||||||
|
args: ["None", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Strip TCP header: Options, Payload",
|
||||||
|
input: "7f900050000fa4b2000cb2a47010bff100000000020405b404020000ffffffffffffffff",
|
||||||
|
expectedOutput: "ffffffffffffffff",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hex",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Strip TCP header",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "To Hex",
|
||||||
|
args: ["None", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Strip TCP header: Input length less than minimum header length",
|
||||||
|
input: "7f900050000fa4b2000cb2a45010bff1000000",
|
||||||
|
expectedOutput: "Need at least 20 bytes for a TCP Header",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hex",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Strip TCP header",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "To Hex",
|
||||||
|
args: ["None", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Strip TCP header: Input length less than data offset",
|
||||||
|
input: "7f900050000fa4b2000cb2a47010bff100000000",
|
||||||
|
expectedOutput: "Input length is less than data offset",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hex",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Strip TCP header",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "To Hex",
|
||||||
|
args: ["None", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
69
tests/operations/tests/StripUDPHeader.mjs
Normal file
69
tests/operations/tests/StripUDPHeader.mjs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Strip UDP header tests.
|
||||||
|
*
|
||||||
|
* @author c65722 []
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Strip UDP header: No payload",
|
||||||
|
input: "8111003500000000",
|
||||||
|
expectedOutput: "",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hex",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Strip UDP header",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "To Hex",
|
||||||
|
args: ["None", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Strip UDP header: Payload",
|
||||||
|
input: "8111003500080000ffffffffffffffff",
|
||||||
|
expectedOutput: "ffffffffffffffff",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hex",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Strip UDP header",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "To Hex",
|
||||||
|
args: ["None", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Strip UDP header: Input length less than header length",
|
||||||
|
input: "81110035000000",
|
||||||
|
expectedOutput: "Need 8 bytes for a UDP Header",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "From Hex",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "Strip UDP header",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: "To Hex",
|
||||||
|
args: ["None", 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
const webpack = require("webpack");
|
const webpack = require("webpack");
|
||||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||||
|
const CompressionPlugin = require("compression-webpack-plugin");
|
||||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||||
const { ModifySourcePlugin, ReplaceOperation } = require("modify-source-webpack-plugin");
|
const { ModifySourcePlugin, ReplaceOperation } = require("modify-source-webpack-plugin");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
const zlib = require("zlib");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Webpack configuration details for use with Grunt.
|
* Webpack configuration details for use with Grunt.
|
||||||
@@ -64,6 +66,21 @@ module.exports = {
|
|||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: "assets/[name].css"
|
filename: "assets/[name].css"
|
||||||
}),
|
}),
|
||||||
|
new CompressionPlugin({
|
||||||
|
filename: "[path][base].gz",
|
||||||
|
algorithm: "gzip",
|
||||||
|
test: /\.(js|css|html)$/,
|
||||||
|
}),
|
||||||
|
new CompressionPlugin({
|
||||||
|
filename: "[path][base].br",
|
||||||
|
algorithm: "brotliCompress",
|
||||||
|
test: /\.(js|css|html)$/,
|
||||||
|
compressionOptions: {
|
||||||
|
params: {
|
||||||
|
[zlib.constants.BROTLI_PARAM_QUALITY]: 11,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
new CopyWebpackPlugin({
|
new CopyWebpackPlugin({
|
||||||
patterns: [
|
patterns: [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user