UNPKG

@swplabs/peanutforwp

Version:

Peanut for WordPress. Build your themes and blocks with components.

135 lines (103 loc) 3.89 kB
const fs = require('fs'); const editorKeyRegex = /^editor_blocks_(?<srcElement>.+)$/i; class BlocksPlugin { constructor({ directory, routes, outputPath, emptyDirectoryOnStart = false }) { this.routes = routes; this.directory = directory; this.outputPath = outputPath; this.blocks = {}; this.filesToEmit = {}; const destDir = `${this.directory}/blocks`; if (emptyDirectoryOnStart && fs.existsSync(destDir)) { fs.rmSync(destDir, { recursive: true }); } } buildJson(key) { const { jsonFile, assets, dir } = this.blocks[key]; try { const metadata = fs.readFileSync(jsonFile, { encoding: 'utf8' }); const data = { $schema: 'https://json.schemastore.org/block.json', ...JSON.parse(metadata), ...assets }; this.filesToEmit[key] = { filename: `${dir.replace(this.outputPath, '')}/block.json`, source: JSON.stringify(data) }; } catch (e) { console.log('[build:webpack:plugins:blocksplugin] error', e?.message); } } apply(compiler) { const { RawSource } = compiler.webpack.sources; compiler.hooks.entryOption.tap('BlocksPlugin', (_context, entry) => { const { routes, directory } = this; Object.keys(entry).forEach((key) => { const match = editorKeyRegex.exec(key); if (match) { const { groups: { srcElement } } = match; const dir = `${directory}/blocks/${srcElement}`; try { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } catch (e) { console.log('[build:webpack:plugins:blocksplugin] error', e?.message); } const { srcPath, hasEditorStyles, hasSrcClient, hasStyles, hasRenderPhp } = routes.find( ({ path }) => path === srcElement ); const jsonFile = `${srcPath}/metadata.json`; if (fs.existsSync(jsonFile)) { const data = { dir, jsonFile, assets: { editorScript: [key] } }; if (hasEditorStyles) data.assets.editorStyle = [`editor_styles_blocks_${srcElement}`]; if (hasSrcClient) data.assets.viewScript = [`blocks_${srcElement}`]; if (hasStyles) data.assets.style = [`styles_blocks_${srcElement}`]; if (hasRenderPhp) data.assets.render = 'file:./render.php'; this.blocks[srcElement] = data; this.buildJson(srcElement); } } }); }); compiler.hooks.watchRun.tap('BlocksPlugin', (compiler) => { if (compiler.modifiedFiles) { Object.keys(this.blocks).forEach((key) => { const { jsonFile } = this.blocks[key]; if (compiler.modifiedFiles.has(jsonFile)) { this.buildJson(key); } }); } }); compiler.hooks.thisCompilation.tap('BlocksPlugin', (compilation) => { Object.keys(this.blocks).forEach((key) => { const { jsonFile } = this.blocks[key]; compilation.fileDependencies.add(jsonFile); }); }); compiler.hooks.compilation.tap('BlocksPlugin', (compilation) => { Object.keys(this.filesToEmit).forEach((key) => { const { filename, source } = this.filesToEmit[key]; // TODO: figure out why it's not included in stats everytime and if we can cache somewhere // TODO: might need to save it "stats" somewhere which would probably fix compilation hash todo as well compilation.emitAsset(filename, new RawSource(source), { component: key }); // TODO: update the compilation hash }); // TODO: commented this out so that it appears in stats everytime. Revisit // this.filesToEmit = {}; }); } } module.exports = { BlocksPlugin };