Skip to content

Commit

Permalink
Create block: Add support for static assets (#28038)
Browse files Browse the repository at this point in the history
* Create block: Add support for static assets

* Create Block: Add implementation for output assets

* Stop using utf-8 encoding when reading static assets
  • Loading branch information
gziolo committed Jan 8, 2021
1 parent 906407b commit 0e59863
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 15 deletions.
4 changes: 4 additions & 0 deletions packages/create-block/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Increase the minimum Node.js version to 12 ([#27934](https://github.com/WordPress/gutenberg/pull/27934)).

### New Features

- Add support for handling static assets with the `assetsPath` field in the external template configuration ([#28038](https://github.com/WordPress/gutenberg/pull/28038)).

### Internal

- Update the demo included in the README file ([#28037](https://github.com/WordPress/gutenberg/pull/28037)).
Expand Down
28 changes: 25 additions & 3 deletions packages/create-block/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,39 @@ Since version `0.19.0` it is possible to use external templates hosted on npm. T

### Template Configuration

It is mandatory to provide the main file for the package that returns a configuration object. It must containing at least `templatesPath` field with the path pointing to the location where template files live (nested folders are also supported).
It is mandatory to provide the main file (`index.js` by default) for the package that returns a configuration object. It must contain at least the `templatesPath` field.

#### `templatesPath`

A mandatory field with the path pointing to the location where template files live (nested folders are also supported). All files without the `.mustache` extension will be ignored.

_Example:_

```js
const { join } = require( 'path' );

module.exports = {
templatesPath: __dirname,
templatesPath: join( __dirname, 'templates' ),
};
```

It is also possible to override the default template configuration using the `defaultValues` field.
#### `assetsPath`

This setting is useful when your template scaffolds a block that uses static assets like images or fonts, which should not be processed. It provides the path pointing to the location where assets are located. They will be copied to the `assets` subfolder in the generated plugin.

_Example:_

```js
const { join } = require( 'path' );

module.exports = {
assetsPath: join( __dirname, 'assets' ),
};
```

#### `defaultValues`

It is possible to override the default template configuration using the `defaultValues` field.

_Example:_

Expand Down
20 changes: 14 additions & 6 deletions packages/create-block/lib/scaffold.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { writeFile } = require( 'fs' ).promises;
const { snakeCase } = require( 'lodash' );
const makeDir = require( 'make-dir' );
const { render } = require( 'mustache' );
const { dirname } = require( 'path' );
const { dirname, join } = require( 'path' );

/**
* Internal dependencies
Expand Down Expand Up @@ -42,7 +42,7 @@ module.exports = async (
info( '' );
info( `Creating a new WordPress block in "${ slug }" folder.` );

const { outputTemplates } = blockTemplate;
const { outputTemplates, outputAssets } = blockTemplate;
const view = {
apiVersion,
namespace,
Expand All @@ -67,10 +67,10 @@ module.exports = async (
await Promise.all(
Object.keys( outputTemplates ).map( async ( outputFile ) => {
// Output files can have names that depend on the slug provided.
const outputFilePath = `${ slug }/${ outputFile.replace(
/\$slug/g,
slug
) }`;
const outputFilePath = join(
slug,
outputFile.replace( /\$slug/g, slug )
);
await makeDir( dirname( outputFilePath ) );
writeFile(
outputFilePath,
Expand All @@ -79,6 +79,14 @@ module.exports = async (
} )
);

await Promise.all(
Object.keys( outputAssets ).map( async ( outputFile ) => {
const outputFilePath = join( slug, 'assets', outputFile );
await makeDir( dirname( outputFilePath ) );
writeFile( outputFilePath, outputAssets[ outputFile ] );
} )
);

await initBlockJSON( view );
await initPackageJSON( view );

Expand Down
32 changes: 26 additions & 6 deletions packages/create-block/lib/templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,23 @@ const getOutputTemplates = async ( outputTemplatesPath ) => {
);
};

const getOutputAssets = async ( outputAssetsPath ) => {
const outputAssetFiles = await glob( '**/*', {
cwd: outputAssetsPath,
dot: true,
} );
return fromPairs(
await Promise.all(
outputAssetFiles.map( async ( outputAssetFile ) => {
const outputAsset = await readFile(
join( outputAssetsPath, outputAssetFile )
);
return [ outputAssetFile, outputAsset ];
} )
)
);
};

const externalTemplateExists = async ( templateName ) => {
try {
await command( `npm view ${ templateName }` );
Expand All @@ -84,6 +101,7 @@ const getBlockTemplate = async ( templateName ) => {
outputTemplates: await getOutputTemplates(
join( __dirname, 'templates', templateName )
),
outputAssets: {},
};
}
if ( ! ( await externalTemplateExists( templateName ) ) ) {
Expand All @@ -108,19 +126,21 @@ const getBlockTemplate = async ( templateName ) => {
cwd: tempCwd,
} );

const { defaultValues = {}, templatesPath } = require( require.resolve(
templateName,
{
paths: [ tempCwd ],
}
) );
const {
defaultValues = {},
templatesPath,
assetsPath,
} = require( require.resolve( templateName, {
paths: [ tempCwd ],
} ) );
if ( ! isObject( defaultValues ) || ! templatesPath ) {
throw new Error();
}

return {
defaultValues,
outputTemplates: await getOutputTemplates( templatesPath ),
outputAssets: assetsPath ? await getOutputAssets( assetsPath ) : {},
};
} catch ( error ) {
throw new CLIError(
Expand Down

0 comments on commit 0e59863

Please sign in to comment.