From dc4afeae38ee2d37d63c691587a7bf1d3b7bcd26 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Tue, 11 Jun 2019 12:54:59 +0200 Subject: [PATCH] Babel macro: Add new Babel macro which handles block.json file transformation --- docs/manifest-devhub.json | 6 ++ package-lock.json | 92 +++++++++++++++++++ package.json | 2 + packages/babel-block.macro/.npmrc | 1 + packages/babel-block.macro/README.md | 13 +++ packages/babel-block.macro/macro.js | 79 ++++++++++++++++ packages/babel-block.macro/package.json | 35 +++++++ .../test/__snapshots__/index.js.snap | 37 ++++++++ .../test/fixtures/block.json | 25 +++++ packages/babel-block.macro/test/index.js | 44 +++++++++ 10 files changed, 334 insertions(+) create mode 100644 packages/babel-block.macro/.npmrc create mode 100644 packages/babel-block.macro/README.md create mode 100644 packages/babel-block.macro/macro.js create mode 100644 packages/babel-block.macro/package.json create mode 100644 packages/babel-block.macro/test/__snapshots__/index.js.snap create mode 100644 packages/babel-block.macro/test/fixtures/block.json create mode 100644 packages/babel-block.macro/test/index.js diff --git a/docs/manifest-devhub.json b/docs/manifest-devhub.json index 94f2172703553..7a5e9d2565b58 100644 --- a/docs/manifest-devhub.json +++ b/docs/manifest-devhub.json @@ -1049,6 +1049,12 @@ "markdown_source": "../packages/autop/README.md", "parent": "packages" }, + { + "title": "@wordpress/babel-block.macro", + "slug": "packages-babel-block.macro", + "markdown_source": "../packages/babel-block.macro/README.md", + "parent": "packages" + }, { "title": "@wordpress/babel-plugin-import-jsx-pragma", "slug": "packages-babel-plugin-import-jsx-pragma", diff --git a/package-lock.json b/package-lock.json index aa639527442e6..2a33d78151a0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3226,6 +3226,13 @@ "@babel/runtime": "^7.4.4" } }, + "@wordpress/babel-block.macro": { + "version": "file:packages/babel-block.macro", + "dev": true, + "requires": { + "babel-plugin-macros": "^2.6.1" + } + }, "@wordpress/babel-plugin-import-jsx-pragma": { "version": "file:packages/babel-plugin-import-jsx-pragma", "dev": true @@ -4671,6 +4678,79 @@ "@types/babel__traverse": "^7.0.6" } }, + "babel-plugin-macros": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.6.1.tgz", + "integrity": "sha512-6W2nwiXme6j1n2erPOnmRiWfObUhWH7Qw1LMi9XZy8cj+KtESu3T6asZvtk5bMQQjX8te35o7CFueiSdL/2NmQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.4.2", + "cosmiconfig": "^5.2.0", + "resolve": "^1.10.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "babel-plugin-tester": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-tester/-/babel-plugin-tester-6.2.1.tgz", + "integrity": "sha512-ELsxMOKGzgVkxWnbd4g9nnbbymQFjGrV9bMO3isuc7KIcdoVm8JoSf252DCoFr4iuS/mMmemM9Q8x+UD37U+6g==", + "dev": true, + "requires": { + "common-tags": "^1.4.0", + "invariant": "^2.2.2", + "lodash.merge": "^4.6.0", + "path-exists": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, "babel-preset-jest": { "version": "24.6.0", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz", @@ -6457,6 +6537,12 @@ "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -14140,6 +14226,12 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "lodash.merge": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", + "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", + "dev": true + }, "lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", diff --git a/package.json b/package.json index 4ff2130f82068..ee085bb1a326b 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "@babel/runtime-corejs3": "7.4.4", "@babel/traverse": "7.4.4", "@octokit/rest": "16.26.0", + "@wordpress/babel-block.macro": "file:packages/babel-block.macro", "@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma", "@wordpress/babel-plugin-makepot": "file:packages/babel-plugin-makepot", "@wordpress/babel-preset-default": "file:packages/babel-preset-default", @@ -87,6 +88,7 @@ "@wordpress/postcss-themes": "file:packages/postcss-themes", "@wordpress/scripts": "file:packages/scripts", "babel-plugin-inline-json-import": "0.3.2", + "babel-plugin-tester": "^6.2.1", "benchmark": "2.1.4", "browserslist": "4.6.2", "chalk": "2.4.1", diff --git a/packages/babel-block.macro/.npmrc b/packages/babel-block.macro/.npmrc new file mode 100644 index 0000000000000..43c97e719a5a8 --- /dev/null +++ b/packages/babel-block.macro/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/babel-block.macro/README.md b/packages/babel-block.macro/README.md new file mode 100644 index 0000000000000..6d06593f6a98d --- /dev/null +++ b/packages/babel-block.macro/README.md @@ -0,0 +1,13 @@ +# Babel Block Macro + +Babel block macro. + +## Installation + +Install the module to your project using [npm](https://www.npmjs.com/). + +```bash +npm install @wordpress/babel-block.macro +``` + +

Code is Poetry.

diff --git a/packages/babel-block.macro/macro.js b/packages/babel-block.macro/macro.js new file mode 100644 index 0000000000000..de20193f6bc08 --- /dev/null +++ b/packages/babel-block.macro/macro.js @@ -0,0 +1,79 @@ +/** + * External dependencies + */ +const { createMacro } = require( 'babel-plugin-macros' ); +const { existsSync, readFileSync } = require( 'fs' ); +const { mapKeys, pick } = require( 'lodash' ); +const { dirname, join, relative } = require( 'path' ); + +function getFilename( [ filenamePath ], state ) { + const filename = filenamePath.evaluate().value; + + return join( + relative( process.cwd(), dirname( state.file.opts.filename ) ), + filename + ); +} + +function readMetadata( filename ) { + if ( ! existsSync( filename ) ) { + throw new Error( `Invalid file name provided: ${ filename }.` ); + } + + const metadataRaw = readFileSync( filename, 'utf8' ); + + return JSON.parse( metadataRaw ); +} + +function formatMetadata( metadata, types ) { + const aliases = { + styleVariations: 'styles', + }; + const replaceWithAlias = ( _, key ) => { + return aliases[ key ] || key; + }; + const whitelistedProperties = [ + 'name', + 'title', + 'category', + 'parent', + 'icon', + 'description', + 'keywords', + 'attributes', + 'styles', + ]; + + const metadataFiltered = pick( + mapKeys( metadata, replaceWithAlias ), + whitelistedProperties + ); + + const metadataNode = types.valueToNode( metadataFiltered ); + /*const translatedProperties = [ + 'title', + 'description', + 'keywords', + ];*/ + + return metadataNode; +} + +function babelBlockMacro( { references, state, babel } ) { + const { types } = babel; + references.default.forEach( ( referencePath ) => { + if ( referencePath.parentPath.type === 'CallExpression' ) { + const metadata = readMetadata( + getFilename( referencePath.parentPath.get( 'arguments' ), state ) + ); + + referencePath.parentPath.replaceWith( formatMetadata( metadata, types ) ); + } else { + throw new Error( + `@wordpress/babel-block.macro can only be used as function call. You tried ${ referencePath.parentPath.type }.`, + ); + } + } ); +} + +module.exports = createMacro( babelBlockMacro ); diff --git a/packages/babel-block.macro/package.json b/packages/babel-block.macro/package.json new file mode 100644 index 0000000000000..d43db1abe51b6 --- /dev/null +++ b/packages/babel-block.macro/package.json @@ -0,0 +1,35 @@ +{ + "name": "@wordpress/babel-block.macro", + "version": "1.0.0-alpha.1", + "description": "Babel block macro.", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "wordpress", + "block", + "babel", + "macro" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/babel-block.macro/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git", + "directory": "packages/babel-block.macro" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "engines": { + "node": ">=10" + }, + "files": [ + "index.js" + ], + "main": "index.js", + "dependencies": { + "babel-plugin-macros": "^2.6.1" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/babel-block.macro/test/__snapshots__/index.js.snap b/packages/babel-block.macro/test/__snapshots__/index.js.snap new file mode 100644 index 0000000000000..f59cec2c2c5a1 --- /dev/null +++ b/packages/babel-block.macro/test/__snapshots__/index.js.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`macros valid metadata file name: valid metadata file name 1`] = ` +" +import macro from '../macro'; +const metadata = macro( './fixtures/block.json' ); + + ↓ ↓ ↓ ↓ ↓ ↓ + +\\"use strict\\"; + +var metadata = { + name: \\"my-plugin/notice\\", + title: \\"Notice\\", + category: \\"common\\", + parent: [\\"core/group\\"], + icon: \\"star\\", + description: \\"Shows warning, error or success notices ...\\", + keywords: [\\"alert\\", \\"message\\"], + attributes: { + message: { + type: \\"string\\", + source: \\"html\\", + selector: \\".meessage\\" + } + }, + styles: [{ + name: \\"default\\", + label: \\"Default\\", + isDefault: true + }, { + name: \\"other\\", + label: \\"Other\\" + }] +}; +" +`; diff --git a/packages/babel-block.macro/test/fixtures/block.json b/packages/babel-block.macro/test/fixtures/block.json new file mode 100644 index 0000000000000..93954c8ad8f48 --- /dev/null +++ b/packages/babel-block.macro/test/fixtures/block.json @@ -0,0 +1,25 @@ +{ + "name": "my-plugin/notice", + "title": "Notice", + "category": "common", + "parent": [ "core/group" ], + "icon": "star", + "description": "Shows warning, error or success notices ...", + "keywords": [ "alert", "message" ], + "textDomain": "my-plugin", + "attributes": { + "message": { + "type": "string", + "source": "html", + "selector": ".meessage" + } + }, + "styleVariations": [ + { "name": "default", "label": "Default", "isDefault": true }, + { "name": "other", "label": "Other" } + ], + "editorScript": "build/editor.js", + "script": "build/main.js", + "editorStyle": "build/editor.css", + "style": "build/style.css" +} diff --git a/packages/babel-block.macro/test/index.js b/packages/babel-block.macro/test/index.js new file mode 100644 index 0000000000000..d5e5f59343fac --- /dev/null +++ b/packages/babel-block.macro/test/index.js @@ -0,0 +1,44 @@ +/** + * External dependencies + */ +import plugin from 'babel-plugin-macros'; +import pluginTester from 'babel-plugin-tester'; + +pluginTester( { + plugin, + babelOptions: { + babelrc: false, + filename: __filename, + presets: [ '@wordpress/babel-preset-default' ], + }, + tests: { + 'valid metadata file name': { + code: ` + import macro from '../macro'; + const metadata = macro( './fixtures/block.json' ); + `, + snapshot: true, + }, + 'invalid metadata file name': { + code: ` + import macro from '../macro'; + const metadata = macro( './invalid-file.json' ); + `, + error: 'Invalid file name provided: packages/babel-block.macro/test/invalid-file.json.', + }, + 'invalid usage: as function argument': { + code: ` + import macro from '../macro'; + const metadata = doSomething( macro ); + `, + error: true, + }, + 'invalid usage: missing file path': { + code: ` + import macro from '../macro'; + const metadata = macro; + `, + error: true, + }, + }, +} );