@@ -4,60 +4,95 @@ import path from "node:path";
44
55export interface RawPluginOptions {
66 /**
7- * Extensions to check in order if the file does not exist .
7+ * File extensions to check in order of priority if the specified file is missing .
88 * If it's a directory, the plugin will look for `dir/index.[ext]`.
9- * @defaultValue ["tsx", "ts", "jsx", "js", "mjs", "mts", "module.css", "module.scss", "css", "scss"]
10- *
11- * You can provide your own extensions to optimize build performance or extend the list based on your use case.
9+ * @defaultValue ["ts", "tsx", "js", "jsx", "mjs", "mts", "module.css", "module.scss", "css", "scss"]
1210 */
1311 ext ?: string [ ] ;
12+
13+ /**
14+ * Custom loader for file processing.
15+ * @defaultValue "text"
16+ */
17+ loader ?: "text" | "base64" | "dataurl" | "file" | "binary" | "default" ;
18+
19+ /**
20+ * Extensions to be treated as text files.
21+ */
22+ textExtensions ?: string [ ] ;
1423}
1524
16- /** Plugin to load `.glsl` files as minified strings */
25+ /**
26+ * ESBuild plugin to enable raw file imports.
27+ *
28+ * This plugin allows importing files with a `?raw` suffix,
29+ * treating them as raw text content. It supports resolving file
30+ * extensions in order of priority and handling custom loaders.
31+ */
1732export const raw : ( options ?: RawPluginOptions ) => Plugin = options => ( {
18- /** generate randmo name to avoid collision among the plugins */
19- name : `raw-${ ( Date . now ( ) * Math . random ( ) ) . toString ( 36 ) . slice ( 0 , 8 ) } ` ,
33+ name : `raw-${ Math . random ( ) . toString ( 36 ) . slice ( 2 , 10 ) } ` ,
2034 setup ( build : PluginBuild ) {
2135 const ext = options ?. ext ?? [
22- "tsx" ,
2336 "ts" ,
24- "jsx " ,
37+ "tsx " ,
2538 "js" ,
39+ "jsx" ,
2640 "mjs" ,
2741 "mts" ,
2842 "module.css" ,
2943 "module.scss" ,
3044 "css" ,
3145 "scss" ,
3246 ] ;
33- build . onResolve ( { filter : / \? r a w $ / } , args => {
34- const filePath = args . path ;
35- return {
36- path : filePath ,
37- pluginData : path . resolve ( args . resolveDir , filePath ) . replace ( / \? r a w $ / , "" ) ,
38- namespace : "raw" ,
39- } ;
40- } ) ;
47+
48+ build . onResolve ( { filter : / \? r a w $ / } , args => ( {
49+ path : args . path ,
50+ pluginData : path . resolve ( args . resolveDir , args . path ) . replace ( / \? r a w $ / , "" ) ,
51+ namespace : "raw" ,
52+ } ) ) ;
53+
4154 build . onLoad ( { filter : / \? r a w $ / , namespace : "raw" } , args => {
4255 let filePath = args . pluginData ;
43- if ( fs . existsSync ( filePath ) && fs . lstatSync ( filePath ) . isDirectory ( ) )
44- filePath += path . sep + "index" ;
45- if ( ! fs . existsSync ( filePath ) )
46- for ( const e of ext )
47- if ( fs . existsSync ( filePath + "." + e ) ) {
48- filePath += "." + e ;
56+ if ( options ?. loader && options . loader !== "text" ) {
57+ return { contents : fs . readFileSync ( filePath , "utf8" ) , loader : options . loader } ;
58+ }
59+
60+ if ( fs . existsSync ( filePath ) && fs . lstatSync ( filePath ) . isDirectory ( ) ) {
61+ filePath = path . join ( filePath , "index" ) ;
62+ }
63+
64+ if ( ! fs . existsSync ( filePath ) ) {
65+ for ( const e of ext ) {
66+ if ( fs . existsSync ( `${ filePath } .${ e } ` ) ) {
67+ filePath += `.${ e } ` ;
4968 break ;
5069 }
51- if ( ! fs . existsSync ( filePath ) )
70+ }
71+ }
72+
73+ if ( ! fs . existsSync ( filePath ) ) {
5274 throw new Error (
5375 /* v8 ignore next */
54- `File not found: ${ args . pluginData } \nWe checked for following extensions: ${ ext . join ( ", " ) } . You can customise by passing { ext: [...]} to raw({ext:[...]}) ` ,
76+ `File not found: ${ args . pluginData } \nChecked extensions: ${ ext . join ( ", " ) } . You can customize this using { ext: [...] }. ` ,
5577 /* v8 ignore next */
5678 ) ;
57- return {
58- contents : fs . readFileSync ( filePath , "utf8" ) ,
59- loader : "text" ,
60- } ;
79+ }
80+
81+ return { contents : fs . readFileSync ( filePath , "utf8" ) , loader : "text" } ;
6182 } ) ;
83+
84+ if ( options ?. textExtensions ?. length ) {
85+ build . onLoad (
86+ {
87+ filter : new RegExp (
88+ `\.(${ options . textExtensions . map ( e => e . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ) . join ( "|" ) } )$` ,
89+ ) ,
90+ } ,
91+ args => ( {
92+ contents : fs . readFileSync ( args . path , "utf8" ) ,
93+ loader : "text" ,
94+ } ) ,
95+ ) ;
96+ }
6297 } ,
6398} ) ;
0 commit comments