22import { basename , join , resolve } from 'node:path' ;
33import { copy } from 'esbuild-plugin-copy' ;
44import { existsSync } from 'node:fs' ;
5+ import { readFile } from 'node:fs/promises' ;
56
67/**
78 * @template {import('esbuild').BuildOptions} T
@@ -41,7 +42,7 @@ export default async function({ rootdir, publicdir }) {
4142 sourcemap : true ,
4243 metafile : true ,
4344 splitting : false ,
44- loader : { '.inline.css' : 'text' , ".svg" : "text" } ,
45+ loader : { '.inline.css' : 'text' , ".svg" : "text" , ".data-url" : "dataurl" } ,
4546 format : "esm" ,
4647 treeShaking : true ,
4748 minify : prod && ! process . env . NOMINIFY ,
@@ -59,6 +60,7 @@ export default async function({ rootdir, publicdir }) {
5960 } ,
6061 conditions : prod ? [ ] : [ "development" ] ,
6162 plugins : [
63+ textLoaderPlugin ,
6264 copy ( {
6365 assets : [ {
6466 from : [ join ( rootdir , "public" , "**/*" ) ] ,
@@ -69,4 +71,66 @@ export default async function({ rootdir, publicdir }) {
6971 } ) ;
7072
7173 return { options, entryPoints }
72- }
74+ }
75+
76+ /** @type {() => import("esbuild").Plugin } */
77+ export const traceJsxRuntimePlugin = ( ) => ( {
78+ name : 'trace-jsx-runtime' ,
79+
80+ setup ( build ) {
81+ build . onResolve ( { filter : / ^ r e a c t \/ j s x - ( d e v - ) ? r u n t i m e $ / } , ( args ) => {
82+ console . warn ( `[jsx-runtime] ${ args . path } imported by ${ args . importer } (kind: ${ args . kind } )` )
83+ return null ;
84+ } )
85+ }
86+ } ) ;
87+
88+ /**
89+ * @param {import("esbuild").PluginBuild } build
90+ * @param {string } suffix
91+ * @param {string } namespace
92+ * @param {(args: import('esbuild').OnLoadArgs) => (import('esbuild').OnLoadResult | null | undefined | Promise<import('esbuild').OnLoadResult | null | undefined>) } callback
93+ */
94+ function setResolve ( build , suffix , namespace , callback ) {
95+ const regText = new RegExp ( "\\?" + suffix + "$" ) ;
96+ // Step 1: intercept imports with ?text
97+ build . onResolve ( { filter : regText } , async ( args ) => {
98+ const rawPath = args . path . replace ( regText , '' ) ;
99+ const result = await build . resolve ( rawPath , {
100+ kind : args . kind ,
101+ importer : args . importer ,
102+ resolveDir : args . resolveDir ,
103+ namespace : args . namespace ,
104+ pluginData : args . pluginData ,
105+ with : args . with ,
106+ } ) ;
107+ if ( result . errors . length > 0 ) {
108+ return { errors : result . errors } ;
109+ }
110+ return {
111+ path : result . path ,
112+ namespace : namespace ,
113+ watchFiles : result . path ? [ result . path ] : [ ] ,
114+ } ;
115+ } ) ;
116+ build . onLoad ( { filter : / .* / , namespace : 'text-import' } , callback ) ;
117+ }
118+ /** @type {import("esbuild").Plugin } */
119+ export const textLoaderPlugin = {
120+ name : 'text-loader' ,
121+ setup ( build ) {
122+
123+ setResolve ( build , "text" , "text-import" , async ( args ) => {
124+ console . log ( "text loader" , args . path ) ;
125+ const contents = await readFile ( args . path , 'utf8' ) ;
126+ return { contents, loader : 'text' , watchFiles : [ args . path ] , } ;
127+ } ) ;
128+
129+ setResolve ( build , "file" , "file-import" , async ( args ) => {
130+ console . log ( "file loader" , args . path ) ;
131+ const contents = await readFile ( args . path ) ;
132+ return { contents, loader : 'file' , watchFiles : [ args . path ] , } ;
133+ } ) ;
134+
135+ } ,
136+ } ;
0 commit comments