1+ /* eslint-disable no-await-in-loop */
2+ /* eslint-disable no-continue */
3+ /* eslint-disable no-restricted-syntax */
14/* eslint-disable import/no-extraneous-dependencies */
25/* eslint-disable no-console */
36import path from 'path'
47import fs from 'fs'
58import { fileURLToPath } from 'url'
69import dotenv from 'dotenv'
710
8- import { build } from 'esbuild'
11+ import { build as compile } from 'esbuild'
912import { htmlPlugin } from '@craftamap/esbuild-plugin-html'
1013import esbuildMxnCopy from 'esbuild-plugin-mxn-copy'
1114import aliasPlugin from 'esbuild-plugin-path-alias'
@@ -17,9 +20,19 @@ const { version } = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'package.
1720const isDevelopment = Boolean ( process . argv . includes ( '--dev' ) )
1821const isRelease = Boolean ( process . argv . includes ( '--release' ) )
1922
20- if ( fs . existsSync ( path . resolve ( __dirname , 'dist' ) ) ) {
23+ const hasCustom = await ( async function checkFolders ( folder , isCustom = false ) {
24+ for ( const file of await fs . promises . readdir ( folder ) ) {
25+ if ( isCustom ) return true
26+ if ( file . startsWith ( '.' ) ) continue
27+ if ( ! file . includes ( '.' ) ) isCustom = await checkFolders ( `${ folder } /${ file } ` , isCustom )
28+ if ( / \. c u s t o m .( j s x ? | c s s ) $ / . test ( file ) ) return true
29+ }
30+ return isCustom
31+ } ( path . resolve ( __dirname , 'src' ) ) )
32+
33+ if ( await fs . existsSync ( path . resolve ( __dirname , 'dist' ) ) ) {
2134 console . log ( 'Cleaning up old build' )
22- fs . rm ( path . resolve ( __dirname , 'dist' ) , { recursive : true } , ( err ) => {
35+ await fs . rm ( path . resolve ( __dirname , 'dist' ) , { recursive : true } , ( err ) => {
2336 if ( err ) console . log ( err )
2437 } )
2538}
@@ -30,7 +43,7 @@ const plugins = [
3043 {
3144 entryPoints : [ 'src/index.jsx' ] ,
3245 filename : 'index.html' ,
33- htmlTemplate : fs . readFileSync ( './public/index.template.html' ) ,
46+ htmlTemplate : await fs . readFileSync ( './public/index.template.html' ) ,
3447 scriptLoading : 'defer' ,
3548 favicon : './public/favicon/favicon.ico' ,
3649 } ,
@@ -55,11 +68,50 @@ if (isDevelopment) {
5568 eslintPlugin ( ) ,
5669 )
5770} else {
71+ if ( hasCustom ) {
72+ plugins . push (
73+ {
74+ name : 'Custom Loader' ,
75+ setup ( build ) {
76+ const customPaths = [ ]
77+ build . onLoad ( { filter : / \. ( j s x ? | c s s ) $ / } , async ( args ) => {
78+ const isNodeModule = / n o d e _ m o d u l e s / . test ( args . path )
79+ if ( ! isNodeModule ) {
80+ const [ base , suffix ] = args . path . split ( '.' )
81+ const newPath = `${ base } .custom.${ suffix } `
82+ if ( await fs . existsSync ( newPath ) ) {
83+ customPaths . push ( newPath )
84+ return {
85+ contents : await fs . readFileSync ( newPath , 'utf8' ) ,
86+ loader : suffix ,
87+ watchFiles : isDevelopment ? [ newPath ] : undefined ,
88+ }
89+ }
90+ }
91+ } )
92+ build . onEnd ( ( ) => {
93+ if ( customPaths . length && ! isDevelopment ) {
94+ console . log ( `
95+ ======================================================
96+ WARNING:
97+ Custom files aren't officially supported
98+ Be sure to watch for breaking changes!
99+
100+ ${ customPaths . map ( ( x , i ) => ` ${ i + 1 } . src/${ x . split ( 'src/' ) [ 1 ] } ` ) . join ( '\n' ) }
101+
102+ ======================================================
103+ ` )
104+ }
105+ } )
106+ } ,
107+ } ,
108+ )
109+ }
58110 console . log ( `Building production version: ${ version } ` )
59111}
60112
61113try {
62- await build ( {
114+ await compile ( {
63115 entryPoints : [ 'src/index.jsx' ] ,
64116 legalComments : 'none' ,
65117 bundle : true ,
89141 ...env . parsed ,
90142 VERSION : version ,
91143 DEVELOPMENT : isDevelopment ,
144+ CUSTOM : hasCustom ,
145+ LOCALES : await fs . promises . readdir ( `${ __dirname } /public/locales` ) ,
92146 } ) ,
93147 } ,
94148 plugins,
0 commit comments