diff --git a/.eslintignore b/.eslintignore
index a4a3d4cbd0924..7228e8b672e90 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -2,5 +2,6 @@ build
build-module
coverage
node_modules
+packages/block-serialization-spec-parser
test/e2e/test-plugins
vendor
diff --git a/.eslintrc.js b/.eslintrc.js
index 18ab9e6e14277..b2564dfc09afa 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -50,10 +50,13 @@ module.exports = {
message: 'Use @wordpress/blob as import path instead.',
},
{
- selector: 'ImportDeclaration[source.value=/^blocks(\\u002F|$)/]',
- message: 'Use @wordpress/blocks as import path instead.',
+ selector: 'ImportDeclaration[source.value=/^block-serialization-spec-parser(\\u002F|$)/]',
+ message: 'Use @wordpress/block-serialization-spec-parser as import path instead.',
},
{
+ selector: 'ImportDeclaration[source.value=/^blocks(\\u002F|$)/]',
+ message: 'Use @wordpress/blocks as import path instead.',
+ },{
selector: 'ImportDeclaration[source.value=/^components(\\u002F|$)/]',
message: 'Use @wordpress/components as import path instead.',
},
diff --git a/bin/create-php-parser.js b/bin/create-php-parser.js
index f5cd5327fd000..0d661ff0f906b 100755
--- a/bin/create-php-parser.js
+++ b/bin/create-php-parser.js
@@ -5,7 +5,7 @@ const phpegjs = require( 'phpegjs' );
const fs = require( 'fs' );
const path = require( 'path' );
-const peg = fs.readFileSync( 'blocks/api/post.pegjs', 'utf8' );
+const peg = fs.readFileSync( 'packages/block-serialization-spec-parser/grammar.pegjs', 'utf8' );
const parser = pegjs.generate(
peg,
diff --git a/bin/generate-public-grammar.js b/bin/generate-public-grammar.js
index 34b5522a6eb0a..aaa3c43bc2888 100755
--- a/bin/generate-public-grammar.js
+++ b/bin/generate-public-grammar.js
@@ -2,7 +2,7 @@
const parser = require( '../node_modules/pegjs/lib/parser.js' );
const fs = require( 'fs' );
const path = require( 'path' );
-const grammarSource = fs.readFileSync( './blocks/api/post.pegjs', 'utf8' );
+const grammarSource = fs.readFileSync( './packages/block-serialization-spec-parser/grammar.pegjs', 'utf8' );
const grammar = parser.parse( grammarSource );
function escape( text ) {
diff --git a/blocks/api/parser.js b/blocks/api/parser.js
index 4aa98b09eba43..5f2ebf531f169 100644
--- a/blocks/api/parser.js
+++ b/blocks/api/parser.js
@@ -10,11 +10,11 @@ import { flow, castArray, mapValues, omit, stubFalse } from 'lodash';
import { autop } from '@wordpress/autop';
import { applyFilters } from '@wordpress/hooks';
import deprecated from '@wordpress/deprecated';
+import { parse as grammarParse } from '@wordpress/block-serialization-spec-parser';
/**
* Internal dependencies
*/
-import { parse as grammarParse } from './post-parser';
import { getBlockType, getUnknownTypeHandlerName } from './registration';
import { createBlock } from './factory';
import { isValidBlock } from './validation';
@@ -365,7 +365,7 @@ export function createBlockWithFallback( blockNode ) {
*
* @return {Function} An implementation which parses the post content.
*/
-export const createParse = ( parseImplementation ) =>
+const createParse = ( parseImplementation ) =>
( content ) => parseImplementation( content ).reduce( ( memo, blockNode ) => {
const block = createBlockWithFallback( blockNode );
if ( block ) {
diff --git a/blocks/api/post-parser.js b/blocks/api/post-parser.js
deleted file mode 100644
index 80f5a105d53e7..0000000000000
--- a/blocks/api/post-parser.js
+++ /dev/null
@@ -1 +0,0 @@
-export * from './post.pegjs';
diff --git a/blocks/api/post-parser.native.js b/blocks/api/post-parser.native.js
deleted file mode 100644
index 7adb6bd3ce0ad..0000000000000
--- a/blocks/api/post-parser.native.js
+++ /dev/null
@@ -1 +0,0 @@
-export * from './post-grammar-parser-pre-generated';
diff --git a/blocks/api/test/parser.js b/blocks/api/test/parser.js
index a9b4b2ce4800c..0b811b9d9a279 100644
--- a/blocks/api/test/parser.js
+++ b/blocks/api/test/parser.js
@@ -16,9 +16,7 @@ import {
default as parsePegjs,
parseWithAttributeSchema,
toBooleanAttributeMatcher,
- createParse,
} from '../parser';
-import { parse as grammarParsePreGenerated } from '../post-grammar-parser-pre-generated';
import {
registerBlockType,
unregisterBlockType,
@@ -549,17 +547,11 @@ describe( 'block parser', () => {
} );
} );
- describe( 'parse() of pegjs parser', () => {
+ describe( 'parse() of @wordpress/block-serialization-spec-parser', () => {
// run the test cases using the PegJS defined parser
testCases( parsePegjs );
} );
- describe( 'parse() of pre-generated parser', () => {
- // run the test cases using the pre-generated parser
- const parsePreGenerated = createParse( grammarParsePreGenerated );
- testCases( parsePreGenerated );
- } );
-
// encapsulate the test cases so we can run them multiple time but with a different parse() function
function testCases( parse ) {
it( 'should parse the post content, including block attributes', () => {
diff --git a/core-blocks/test/full-content.js b/core-blocks/test/full-content.js
index afa71247575ad..0dc2c9005143f 100644
--- a/core-blocks/test/full-content.js
+++ b/core-blocks/test/full-content.js
@@ -10,12 +10,12 @@ import { format } from 'util';
* WordPress dependencies
*/
import { getBlockTypes, parse, serialize } from '@wordpress/blocks';
+import { parse as grammarParse } from '@wordpress/block-serialization-spec-parser';
/**
* Internal dependencies
*/
import { registerCoreBlocks } from '../';
-import { parse as grammarParse } from '../../blocks/api/post.pegjs';
const fixturesDir = path.join( __dirname, 'fixtures' );
diff --git a/lib/client-assets.php b/lib/client-assets.php
index cde5919bab1af..1fc9d11ee92e5 100644
--- a/lib/client-assets.php
+++ b/lib/client-assets.php
@@ -203,6 +203,13 @@ function gutenberg_register_scripts_and_styles() {
filemtime( gutenberg_dir_path() . 'build/dom/index.js' ),
true
);
+ wp_register_script(
+ 'wp-block-serialization-spec-parser',
+ gutenberg_url( 'build/block-serialization-spec-parser/index.js' ),
+ array(),
+ filemtime( gutenberg_dir_path() . 'build/block-serialization-spec-parser/index.js' ),
+ true
+ );
wp_add_inline_script(
'wp-dom',
gutenberg_get_script_polyfill( array(
@@ -290,7 +297,7 @@ function gutenberg_register_scripts_and_styles() {
wp_register_script(
'wp-blocks',
gutenberg_url( 'build/blocks/index.js' ),
- array( 'wp-blob', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-shortcode', 'wp-data', 'lodash' ),
+ array( 'wp-blob', 'wp-deprecated', 'wp-dom', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-shortcode', 'wp-block-serialization-spec-parser', 'wp-data', 'lodash' ),
filemtime( gutenberg_dir_path() . 'build/blocks/index.js' ),
true
);
diff --git a/package-lock.json b/package-lock.json
index a65035568ca77..d604bb389330b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3029,6 +3029,9 @@
"@wordpress/blob": {
"version": "file:packages/blob"
},
+ "@wordpress/block-serialization-spec-parser": {
+ "version": "file:packages/block-serialization-spec-parser"
+ },
"@wordpress/browserslist-config": {
"version": "file:packages/browserslist-config",
"dev": true
@@ -15411,29 +15414,6 @@
"integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=",
"dev": true
},
- "pegjs-loader": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/pegjs-loader/-/pegjs-loader-0.5.4.tgz",
- "integrity": "sha512-ViH8WwUkc/N8H59zuarORrgCi7uxn+gDIq+Ydriw1GFJi/oUg2xvhsgDDujO6dAxRsxXMgqWESx6TKYIqHorqA==",
- "dev": true,
- "requires": {
- "loader-utils": "^0.2.5"
- },
- "dependencies": {
- "loader-utils": {
- "version": "0.2.17",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
- "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
- "dev": true,
- "requires": {
- "big.js": "^3.1.3",
- "emojis-list": "^2.0.0",
- "json5": "^0.5.0",
- "object-assign": "^4.0.1"
- }
- }
- }
- },
"pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
diff --git a/package.json b/package.json
index 07fa9c52fa721..391fd95d665f9 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"@wordpress/api-fetch": "file:packages/api-fetch",
"@wordpress/autop": "file:packages/autop",
"@wordpress/blob": "file:packages/blob",
+ "@wordpress/block-serialization-spec-parser": "file:packages/block-serialization-spec-parser",
"@wordpress/components": "file:packages/components",
"@wordpress/compose": "file:packages/compose",
"@wordpress/core-data": "file:packages/core-data",
@@ -105,7 +106,6 @@
"node-sass": "4.9.2",
"path-type": "3.0.0",
"pegjs": "0.10.0",
- "pegjs-loader": "0.5.4",
"phpegjs": "1.0.0-beta7",
"postcss-color-function": "4.0.1",
"postcss-loader": "2.1.3",
@@ -145,7 +145,7 @@
"scripts": {
"prebuild": "npm run check-engines",
"clean:packages": "rimraf ./packages/*/build ./packages/*/build-module ./packages/*/build-style",
- "prebuild:packages": "npm run clean:packages && cross-env INCLUDE_PACKAGES=babel-plugin-import-jsx-pragma,postcss-themes SKIP_JSX_PRAGMA_TRANSFORM=1 node ./bin/packages/build.js",
+ "prebuild:packages": "npm run clean:packages && lerna run build && cross-env INCLUDE_PACKAGES=babel-plugin-import-jsx-pragma,postcss-themes SKIP_JSX_PRAGMA_TRANSFORM=1 node ./bin/packages/build.js",
"build:packages": "cross-env EXCLUDE_PACKAGES=babel-plugin-import-jsx-pragma,postcss-themes node ./bin/packages/build.js",
"build": "npm run build:packages && cross-env NODE_ENV=production webpack",
"check-engines": "check-node-version --package",
diff --git a/packages/block-serialization-spec-parser/.npmrc b/packages/block-serialization-spec-parser/.npmrc
new file mode 100644
index 0000000000000..43c97e719a5a8
--- /dev/null
+++ b/packages/block-serialization-spec-parser/.npmrc
@@ -0,0 +1 @@
+package-lock=false
diff --git a/packages/block-serialization-spec-parser/README.md b/packages/block-serialization-spec-parser/README.md
new file mode 100644
index 0000000000000..36c93ddb6a236
--- /dev/null
+++ b/packages/block-serialization-spec-parser/README.md
@@ -0,0 +1,26 @@
+# @wordpress/block-serialization-spec-parser
+
+This library contains the grammar file (`grammar.pegjs`) for WordPress posts which is a block serialization _specification_ which is used to generate the actual _parser_ which is also bundled in this package.
+
+PEG parser generators are available in many languages, though different libraries may require some translation of this grammar into their syntax. For more information see:
+* https://pegjs.org
+* https://en.wikipedia.org/wiki/Parsing_expression_grammar
+
+## Installation
+
+Install the module
+
+```bash
+npm install @wordpress/block-serialization-spec-parser --save
+```
+
+## Usage
+
+```js
+import { parse } from '@wordpress/block-serialization-spec-parser';
+
+parse( '' );
+// [{"attrs": null, "blockName": "core/more", "innerBlocks": [], "innerHTML": ""}]
+```
+
+