Skip to content

Commit ff090cd

Browse files
committed
refactor: improve raw plugin file handling and error messages
1 parent 6df8c03 commit ff090cd

1 file changed

Lines changed: 59 additions & 35 deletions

File tree

lib/src/index.ts

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@ import type { Plugin, PluginBuild } from "esbuild";
22
import fs from "node:fs";
33
import path from "node:path";
44

5+
const DEFAULT_EXT_ORDER_LIST = [
6+
"ts",
7+
"tsx",
8+
"js",
9+
"jsx",
10+
"mjs",
11+
"mts",
12+
"module.css",
13+
"module.scss",
14+
"css",
15+
"scss",
16+
];
17+
518
export interface RawPluginOptions {
619
/**
720
* File extensions to check in order of priority if the specified file is missing.
@@ -29,67 +42,78 @@ export interface RawPluginOptions {
2942
* treating them as raw text content. It supports resolving file
3043
* extensions in order of priority and handling custom loaders.
3144
*/
32-
export const raw: (options?: RawPluginOptions) => Plugin = options => ({
33-
name: `esbuild-raw-plugin`,
45+
export const raw = (options?: RawPluginOptions): Plugin => ({
46+
name: "esbuild-raw-plugin",
3447
setup(build: PluginBuild) {
35-
const ext = options?.ext ?? [
36-
"ts",
37-
"tsx",
38-
"js",
39-
"jsx",
40-
"mjs",
41-
"mts",
42-
"module.css",
43-
"module.scss",
44-
"css",
45-
"scss",
46-
];
48+
const ext = options?.ext ?? DEFAULT_EXT_ORDER_LIST;
4749

48-
build.onResolve({ filter: /\?raw$/ }, args => ({
49-
path: args.path,
50-
pluginData: path.resolve(args.resolveDir, args.path).replace(/\?raw$/, ""),
51-
namespace: "raw",
52-
}));
50+
build.onResolve({ filter: /\?(raw|text|buffer|binary|base64|dataurl|file)$/ }, args => {
51+
const [filepath, query] = args.path.split("?");
52+
return {
53+
path: filepath,
54+
namespace: "raw",
55+
pluginData: {
56+
fullPath: path.resolve(args.resolveDir, filepath),
57+
query,
58+
},
59+
};
60+
});
5361

54-
build.onLoad({ filter: /\?raw$/, namespace: "raw" }, args => {
55-
let filePath = args.pluginData;
56-
if (options?.loader && options.loader !== "text") {
57-
return { contents: fs.readFileSync(filePath, "utf8"), loader: options.loader };
58-
}
62+
build.onLoad({ filter: /.*/, namespace: "raw" }, args => {
63+
let { fullPath, query } = args.pluginData;
64+
let filePath = fullPath;
5965

6066
if (fs.existsSync(filePath) && fs.lstatSync(filePath).isDirectory()) {
6167
filePath = path.join(filePath, "index");
6268
}
6369

6470
if (!fs.existsSync(filePath)) {
65-
for (const e of ext) {
66-
if (fs.existsSync(`${filePath}.${e}`)) {
67-
filePath += `.${e}`;
68-
break;
69-
}
71+
const resolved = ext
72+
.map(e => e.replace(/^\./, ""))
73+
.find(e => fs.existsSync(`${filePath}.${e}`));
74+
if (resolved) {
75+
filePath += `.${resolved}`;
7076
}
7177
}
7278

7379
if (!fs.existsSync(filePath)) {
7480
throw new Error(
75-
/* v8 ignore next */
76-
`File not found: ${args.pluginData}\nChecked extensions: ${ext.join(", ")}. You can customize this using { ext: [...] }.`,
77-
/* v8 ignore next */
81+
`File not found: ${fullPath}\nChecked extensions: ${ext.join(", ")}.\nYou can customize extensions list using { ext: [...] }.`,
7882
);
7983
}
8084

81-
return { contents: fs.readFileSync(filePath, "utf8"), loader: "text" };
85+
const buffer = fs.readFileSync(filePath);
86+
const suffix = query?.toLowerCase();
87+
88+
let loader = options?.loader ?? "text";
89+
switch (suffix) {
90+
case "text":
91+
loader = "text";
92+
break;
93+
case "buffer":
94+
case "binary":
95+
loader = "binary";
96+
break;
97+
case "file":
98+
case "base64":
99+
case "dataurl":
100+
loader = suffix;
101+
}
102+
103+
return { contents: buffer, loader };
82104
});
83105

84106
if (options?.textExtensions?.length) {
85107
build.onLoad(
86108
{
87109
filter: new RegExp(
88-
`\.(${options.textExtensions.map(e => e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})$`,
110+
`\\.(${options.textExtensions
111+
.map(e => e.replace(/^\./, "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
112+
.join("|")})$`,
89113
),
90114
},
91115
args => ({
92-
contents: fs.readFileSync(args.path, "utf8"),
116+
contents: fs.readFileSync(args.path),
93117
loader: "text",
94118
}),
95119
);

0 commit comments

Comments
 (0)