add [root] and [internal-path] placeholders
- [root] prevents asset path leading outside of build context - [internal-path] is like [path] guarded by [root] (`[root][path]`)
This commit is contained in:
parent
d3a0f8de03
commit
85dd7b71d2
|
@ -6,7 +6,7 @@
|
|||
"use strict";
|
||||
|
||||
const mime = require("mime-types");
|
||||
const { basename, extname } = require("path");
|
||||
const { basename, extname, posix } = require("path");
|
||||
const util = require("util");
|
||||
const Chunk = require("./Chunk");
|
||||
const Module = require("./Module");
|
||||
|
@ -29,6 +29,8 @@ const prepareId = id => {
|
|||
|
||||
return id.replace(/(^[.-]|[^a-zA-Z0-9_-])+/g, "_");
|
||||
};
|
||||
const internalPath = path =>
|
||||
path.replace(/^(\.\.\/)+/, m => "_/".repeat(m.length / 3));
|
||||
|
||||
const hashLength = (replacer, handler, assetInfo, hashName) => {
|
||||
const fn = (match, arg, input) => {
|
||||
|
@ -79,6 +81,18 @@ const replacer = (value, allowEmpty) => {
|
|||
return fn;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} input input
|
||||
* @param {number} index match index
|
||||
* @returns {string} replaced path
|
||||
*/
|
||||
const rootReplacer = (input, index) => {
|
||||
const subPath = input.slice(index + 6 /* "[root]".length */);
|
||||
const normalized = posix.normalize(subPath);
|
||||
|
||||
return input.slice(0, index) + internalPath(normalized);
|
||||
};
|
||||
|
||||
const deprecationCache = new Map();
|
||||
const deprecatedFunction = (() => () => {})();
|
||||
const deprecated = (fn, message, code) => {
|
||||
|
@ -152,6 +166,10 @@ const replacePathVariables = (path, data, assetInfo) => {
|
|||
replacements.set("query", replacer(query, true));
|
||||
replacements.set("fragment", replacer(fragment, true));
|
||||
replacements.set("path", replacer(path, true));
|
||||
replacements.set(
|
||||
"internal-path",
|
||||
replacer(() => internalPath(path), true)
|
||||
);
|
||||
replacements.set("base", replacer(base));
|
||||
replacements.set("name", replacer(name));
|
||||
replacements.set("ext", replacer(ext, true));
|
||||
|
@ -325,6 +343,17 @@ const replacePathVariables = (path, data, assetInfo) => {
|
|||
return match;
|
||||
});
|
||||
|
||||
const regexp = /\[root\]/gi;
|
||||
const matches = [];
|
||||
let match;
|
||||
|
||||
while ((match = regexp.exec(path))) matches.push(match.index);
|
||||
if (matches.length) {
|
||||
for (let i = matches.length - 1; i >= 0; i--) {
|
||||
path = rootReplacer(path, matches[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
|
|
|
@ -739,7 +739,7 @@ const applyOutputDefaults = (
|
|||
});
|
||||
|
||||
F(output, "module", () => !!outputModule);
|
||||
D(output, "filename", output.module ? "[name].mjs" : "[name].js");
|
||||
D(output, "filename", output.module ? "[root][name].mjs" : "[root][name].js");
|
||||
F(output, "iife", () => !output.module);
|
||||
D(output, "importFunctionName", "import");
|
||||
D(output, "importMetaName", "import.meta");
|
||||
|
|
|
@ -300,7 +300,7 @@ describe("snapshots", () => {
|
|||
"assetModuleFilename": "[hash][ext][query]",
|
||||
"asyncChunks": true,
|
||||
"charset": true,
|
||||
"chunkFilename": "[name].js",
|
||||
"chunkFilename": "[root][name].js",
|
||||
"chunkFormat": "array-push",
|
||||
"chunkLoadTimeout": 120000,
|
||||
"chunkLoading": "jsonp",
|
||||
|
@ -308,8 +308,8 @@ describe("snapshots", () => {
|
|||
"clean": undefined,
|
||||
"compareBeforeEmit": true,
|
||||
"crossOriginLoading": false,
|
||||
"cssChunkFilename": "[name].css",
|
||||
"cssFilename": "[name].css",
|
||||
"cssChunkFilename": "[root][name].css",
|
||||
"cssFilename": "[root][name].css",
|
||||
"devtoolFallbackModuleFilenameTemplate": undefined,
|
||||
"devtoolModuleFilenameTemplate": undefined,
|
||||
"devtoolNamespace": "webpack",
|
||||
|
@ -330,7 +330,7 @@ describe("snapshots", () => {
|
|||
"forOf": true,
|
||||
"module": undefined,
|
||||
},
|
||||
"filename": "[name].js",
|
||||
"filename": "[root][name].js",
|
||||
"globalObject": "self",
|
||||
"hashDigest": "hex",
|
||||
"hashDigestLength": 20,
|
||||
|
@ -879,8 +879,8 @@ describe("snapshots", () => {
|
|||
- "externalsType": "var",
|
||||
+ "externalsType": "module",
|
||||
@@ ... @@
|
||||
- "chunkFilename": "[name].js",
|
||||
+ "chunkFilename": "[name].mjs",
|
||||
- "chunkFilename": "[root][name].js",
|
||||
+ "chunkFilename": "[root][name].mjs",
|
||||
@@ ... @@
|
||||
- "dynamicImport": undefined,
|
||||
+ "dynamicImport": true,
|
||||
|
@ -888,8 +888,8 @@ describe("snapshots", () => {
|
|||
- "module": undefined,
|
||||
+ "module": true,
|
||||
@@ ... @@
|
||||
- "filename": "[name].js",
|
||||
+ "filename": "[name].mjs",
|
||||
- "filename": "[root][name].js",
|
||||
+ "filename": "[root][name].mjs",
|
||||
@@ ... @@
|
||||
- "hotUpdateChunkFilename": "[id].[fullhash].hot-update.js",
|
||||
+ "hotUpdateChunkFilename": "[id].[fullhash].hot-update.mjs",
|
||||
|
@ -994,15 +994,15 @@ describe("snapshots", () => {
|
|||
+ Received
|
||||
|
||||
@@ ... @@
|
||||
- "chunkFilename": "[name].js",
|
||||
- "chunkFilename": "[root][name].js",
|
||||
+ "chunkFilename": "[id].bundle.js",
|
||||
@@ ... @@
|
||||
- "cssChunkFilename": "[name].css",
|
||||
- "cssFilename": "[name].css",
|
||||
- "cssChunkFilename": "[root][name].css",
|
||||
- "cssFilename": "[root][name].css",
|
||||
+ "cssChunkFilename": "[id].bundle.css",
|
||||
+ "cssFilename": "bundle.css",
|
||||
@@ ... @@
|
||||
- "filename": "[name].js",
|
||||
- "filename": "[root][name].js",
|
||||
+ "filename": "bundle.js",
|
||||
`)
|
||||
);
|
||||
|
@ -1012,15 +1012,15 @@ describe("snapshots", () => {
|
|||
+ Received
|
||||
|
||||
@@ ... @@
|
||||
- "chunkFilename": "[name].js",
|
||||
- "chunkFilename": "[root][name].js",
|
||||
+ "chunkFilename": "[id].js",
|
||||
@@ ... @@
|
||||
- "cssChunkFilename": "[name].css",
|
||||
- "cssFilename": "[name].css",
|
||||
- "cssChunkFilename": "[root][name].css",
|
||||
- "cssFilename": "[root][name].css",
|
||||
+ "cssChunkFilename": "[id].css",
|
||||
+ "cssFilename": "[id].css",
|
||||
@@ ... @@
|
||||
- "filename": "[name].js",
|
||||
- "filename": "[root][name].js",
|
||||
+ "filename": [Function filename],
|
||||
`)
|
||||
);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import txt from "asset/1.txt";
|
||||
|
||||
it("should compile and run", () => {
|
||||
expect(fs.readFileSync(path.resolve(__dirname, "..", txt)).toString()).toMatch("text");
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
findBundle(i) {
|
||||
return `./_/bundle${i}.js`;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
const path = require("path");
|
||||
|
||||
const base = {
|
||||
mode: "production",
|
||||
target: "node",
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.txt$/,
|
||||
type: "asset/resource"
|
||||
}
|
||||
]
|
||||
},
|
||||
output: {
|
||||
filename: "[root]../bundle0.js",
|
||||
assetModuleFilename: "[root][path][name]-[hash][ext]"
|
||||
},
|
||||
resolve: {
|
||||
modules: [path.resolve(__dirname, "..", "..", "..", "fixtures")]
|
||||
},
|
||||
stats: {
|
||||
errorDetails: true
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {import("../../../../types").Configuration[]} */
|
||||
module.exports = [
|
||||
base,
|
||||
{
|
||||
...base,
|
||||
output: {
|
||||
filename: "[root]../bundle1.js",
|
||||
assetModuleFilename: "some/dir/[root][path][name]-[hash][ext]"
|
||||
}
|
||||
}
|
||||
];
|
|
@ -0,0 +1 @@
|
|||
text
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "asset",
|
||||
"version": "1.0.0"
|
||||
}
|
Loading…
Reference in New Issue