@gravityforms/gulp-tasks
Version:
Configurable Gulp tasks for use in Gravity Forms projects.
130 lines (113 loc) • 5.2 kB
JavaScript
const fs = require( 'fs' );
const path = require( 'path' );
const packagesDir = path.resolve( __dirname, '../../../' );
const componentsPath = path.join( packagesDir, 'components' );
const gulpTasksPath = path.join( packagesDir, 'gulp-tasks' );
const { deleteDirectory, execShellCommand } = require( './util' );
const { trailingSlashIt, untrailingSlashIt } = require( '../utils/tools' );
const getEntryPointContent = ( imports, context, componentMap ) => {
return `if ( window.gformComponentDistPath ) {
__webpack_public_path__ = window.gformComponentDistPath;
}
${ imports.join( '\n' ) }
const getGlobalContainer = ( rootNamespace ) => {
if ( ! window[ rootNamespace ] ) window[ rootNamespace ] = {};
if ( ! window[ rootNamespace ].components ) window[ rootNamespace ].components = {};
if ( ! window[ rootNamespace ].components.${ context } ) window[ rootNamespace ].components.${ context } = {};
return window[ rootNamespace ].components.${ context };
};
const initModules = (container) => {
container.html = container.html || { elements: {}, modules: {} };
container.react = container.react || { elements: {}, modules: {} };
};
const init = () => {
const rootNamespace = window.gformComponentNamespace || 'gform';
const container = getGlobalContainer( rootNamespace );
initModules( container );
${ Object.entries( componentMap ).map( ( [ key, value ] ) => {
return ` window[ rootNamespace ].${ key } = ${ value };`;
} ).join( '\n' ) }
};
init();
`;
};
const generateEntryPoint = ( context ) => {
const imports = [];
const componentMap = {};
const mappingFile = path.join( componentsPath, 'dist', 'mappings', `${ context }.js` );
if ( fs.existsSync( mappingFile ) ) {
const components = require( mappingFile );
const sortedComponents = components.sort( ( a, b ) => {
if ( ! a.defaultExport && ! b.defaultExport ) {
return 0;
}
if ( ! a.defaultExport ) {
return 1;
}
if ( ! b.defaultExport ) {
return -1;
}
return a.defaultExport.localeCompare( b.defaultExport );
} );
sortedComponents.forEach( ( component ) => {
const { defaultExport = '', namedExports = [], externalPath = '', importPath = '' } = component;
// todo: wire up to config in case people want the svgs in the bundle, even though it would bloat the library massively
if ( importPath.includes( `react/${ context }/elements/Svgs/` ) ) {
return;
}
const defaultExportName = importPath.includes( `react/${ context }` ) ? `React${ defaultExport }` : defaultExport;
const parsedImportPath = `../../../${ trailingSlashIt( importPath ) }${ defaultExport || namedExports[ 0 ] }`;
const importPathParts = untrailingSlashIt( importPath ).split( '/' );
// Generate import statements
if ( ! defaultExport && ! namedExports.length ) {
return;
}
imports.push( `import ${ defaultExportName ? defaultExportName : '' }${ defaultExportName && namedExports.length ? ', ' : '' }${ namedExports.length ? `{ ${ namedExports.join( ', ' ) } }` : '' } from '${ parsedImportPath }';` );
// Construct the component map
if ( defaultExport ) {
// If the import path is nested, we need to handle it differently. Done for React, which can go one level deeper.
if ( importPathParts.length > 3 && importPath.includes( `react/${ context }` ) ) {
componentMap[ `${ externalPath }.${ importPathParts[ 3 ] }` ] = '{}';
componentMap[ `${ externalPath }.${ importPathParts[ 3 ] }.${ defaultExport }` ] = defaultExportName;
} else {
componentMap[ `${ externalPath }.${ defaultExport }` ] = defaultExportName;
}
}
namedExports.forEach( ( namedExport ) => {
componentMap[ `${ externalPath }.${ defaultExport }.${ namedExport }` ] = namedExport;
} );
} );
}
// Write the entry point content to a file in the components package which we can use to generate the release bundle
const outputDir = path.join( componentsPath, 'dist', 'js', 'entry' );
if ( ! fs.existsSync( outputDir ) ) {
fs.mkdirSync( outputDir, { recursive: true } );
}
if ( imports.length ) {
fs.writeFileSync( path.join( outputDir, `${ context }.js` ), getEntryPointContent( imports, context, componentMap ) );
}
};
function generateEntryPoints() {
[ 'admin', 'theme' ].forEach( ( context ) => {
generateEntryPoint( context );
} );
}
async function init() {
await deleteDirectory( path.join( componentsPath, 'dist' ) );
await execShellCommand( `cd "${ gulpTasksPath }" && npm run export:components`, true );
await execShellCommand( `cd "${ gulpTasksPath }" && gulp postcss:componentsAdminDistCss && gulp postcss:componentsCommonDistCss && gulp postcss:componentsThemeDistCss`, true );
generateEntryPoints();
await execShellCommand( `cd "${ gulpTasksPath }" && cross-env NODE_ENV=admincomponentsdev npx webpack && cross-env NODE_ENV=admincomponentsprod npx webpack --mode production`, true );
}
( async () => {
try {
if ( ! fs.existsSync( componentsPath ) ) {
console.log( 'components package not found. Skipping dist generation for that package.' );
return;
}
await init();
} catch ( err ) {
console.error( 'An error occurred during generating component dist files: ', err );
}
} )();