WooCommerce Docs: Add support for more core block conversion (#39244)

* WIP extend support for frontmatter in manifests.

* Change some of the prop names in the frontmatter support, add tests.

* WIP support new frontmatter in plugin.

* Improve category processing.

* restructure the docs to have a nested category with no index.

* Add WP test stubs to dev.

* Add tests for the ManifestProcessor.

* Add param docs to function

* Store post meta on posts when they are updated or created. Add supporting tests.

* WIP supporting more core block types.

* Fix bugs in conversion.

* Adjust conversion for issues with tables, blockquotes, code.

* Resolve pnpm lock conflicts

* Return manifest to state in trunk.

* Return pnpm lock to trunk state.

* Update fixture for new md content.
This commit is contained in:
Sam Seay 2023-07-22 12:22:55 +08:00 committed by Kyle Nel
parent 0243bfdc42
commit b128f07af2
No known key found for this signature in database
5 changed files with 99 additions and 12 deletions

View File

@ -7,3 +7,14 @@ post_title: Local Development
1. Install 1. Install
2. Configure 2. Configure
3. Profit! 3. Profit!
```
$ cd /path/to/woocommerce-docs
```
> This is a blockquote.
| First Header | Second Header |
| ------------ | ------------- |
| Content Cell | Content Cell |
| Content Cell | Content Cell |

View File

@ -5,6 +5,7 @@ namespace WooCommerceDocs\Blocks;
use League\CommonMark\Environment\Environment; use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\MarkdownConverter; use League\CommonMark\MarkdownConverter;
use League\CommonMark\Extension\GithubFlavoredMarkdownExtension;
/** /**
* Class MarkdownParser * Class MarkdownParser
@ -23,6 +24,7 @@ class BlockConverter {
public function __construct() { public function __construct() {
$environment = new Environment(); $environment = new Environment();
$environment->addExtension( new CommonMarkCoreExtension() ); $environment->addExtension( new CommonMarkCoreExtension() );
$environment->addExtension( new GithubFlavoredMarkdownExtension() );
$this->parser = new MarkdownConverter( $environment ); $this->parser = new MarkdownConverter( $environment );
} }
@ -75,11 +77,18 @@ class BlockConverter {
* @param \DOMNode $node The DOM node. * @param \DOMNode $node The DOM node.
*/ */
private function convert_node_to_block( $node ) { private function convert_node_to_block( $node ) {
$node_name = $node->nodeName; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $node_name = $node->nodeName; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$node_value = $node->nodeValue; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $node_value = $node->nodeValue; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$node_content = $this->convert_child_nodes_to_blocks( $node );
$node_content = $this->convert_child_nodes_to_blocks_or_html( $node );
switch ( $node_name ) { switch ( $node_name ) {
case 'blockquote':
return $this->create_block( 'quote', $node_name, $node_content );
case 'table':
return $this->create_block( 'table', $node_name, $node_content );
case 'pre':
return $this->create_block( 'code', $node_name, $node_content );
case 'p': case 'p':
return $this->create_block( 'paragraph', $node_name, $node_content ); return $this->create_block( 'paragraph', $node_name, $node_content );
case 'h1': case 'h1':
@ -103,7 +112,7 @@ class BlockConverter {
case 'hr': case 'hr':
return $this->create_block( 'separator', $node_name, null ); return $this->create_block( 'separator', $node_name, null );
default: default:
return $this->create_block( 'paragraph', $node_value ); return $node_value;
} }
} }
@ -124,20 +133,27 @@ class BlockConverter {
if ( 'hr' === $node_name ) { if ( 'hr' === $node_name ) {
$block_html .= "<{$node_name} class=\"wp-block-separator has-alpha-channel-opacity\" />\n"; $block_html .= "<{$node_name} class=\"wp-block-separator has-alpha-channel-opacity\" />\n";
} elseif ( null !== $content ) { } elseif ( null !== $content ) {
$block_html .= "<{$node_name}>{$content}</{$node_name}>\n"; // Gutenberg seems to require class name to avoid block recovery error on some blocks.
if ( 'pre' === $node_name ) {
$block_html .= "<pre class=\"wp-block-code\">{$content}</pre>\n";
} elseif ( 'blockquote' === $node_name ) {
$block_html .= "<blockquote class=\"wp-block-quote\">{$content}</blockquote>\n";
} elseif ( 'table' === $node_name ) {
$block_html .= "<figure class=\"wp-block-table\"><table>{$content}</table></figure>\n";
} else {
$block_html .= "<{$node_name}>{$content}</{$node_name}>\n";
}
} }
$block_html .= "<!-- /wp:{$block_name} -->\n"; $block_html .= "<!-- /wp:{$block_name} -->\n";
return $block_html; return $block_html;
} }
/** /**
* Convert child nodes to blocks. * Convert child nodes to blocks or HTML.
* *
* @param \DOMNode $node The DOM node. * @param \DOMNode $node The DOM node.
*/ */
private function convert_child_nodes_to_blocks( $node ) { private function convert_child_nodes_to_blocks_or_html( $node ) {
$content = ''; $content = '';
foreach ( $node->childNodes as $child_node ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase foreach ( $node->childNodes as $child_node ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
@ -145,18 +161,24 @@ class BlockConverter {
$node_name = $child_node->nodeName; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $node_name = $child_node->nodeName; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
if ( XML_ELEMENT_NODE === $node_type ) { if ( XML_ELEMENT_NODE === $node_type ) {
if ( 'a' === $node_name ) { if ( 'td' === $node_name || 'thead' === $node_name || 'tbody' === $node_name || 'tr' === $node_name || 'th' === $node_name ) {
$inline_content = $this->convert_child_nodes_to_blocks_or_html( $child_node );
$content .= "<{$node_name}>{$inline_content}</{$node_name}>";
} elseif ( 'a' === $node_name ) {
$href = esc_url( $child_node->getAttribute( 'href' ) ); $href = esc_url( $child_node->getAttribute( 'href' ) );
$link_content = $this->convert_child_nodes_to_blocks( $child_node ); $link_content = $this->convert_child_nodes_to_blocks_or_html( $child_node );
$content .= "<a href=\"{$href}\">{$link_content}</a>"; $content .= "<a href=\"{$href}\">{$link_content}</a>";
} elseif ( 'em' === $node_name || 'strong' === $node_name ) { } elseif ( 'em' === $node_name || 'strong' === $node_name ) {
$inline_content = $this->convert_child_nodes_to_blocks( $child_node ); $inline_content = $this->convert_child_nodes_to_blocks_or_html( $child_node );
$content .= "<{$node_name}>{$inline_content}</{$node_name}>"; $content .= "<{$node_name}>{$inline_content}</{$node_name}>";
} elseif ( 'img' === $node_name ) { } elseif ( 'img' === $node_name ) {
// Only handle images as inline content for now due to how Markdown is processed by CommonMark. // Only handle images as inline content for now due to how Markdown is processed by CommonMark.
$src = esc_url( $child_node->getAttribute( 'src' ) ); $src = esc_url( $child_node->getAttribute( 'src' ) );
$alt = esc_attr( $child_node->getAttribute( 'alt' ) ); $alt = esc_attr( $child_node->getAttribute( 'alt' ) );
$content .= "<img src=\"{$src}\" alt=\"{$alt}\" />"; $content .= "<img src=\"{$src}\" alt=\"{$alt}\" />";
} elseif ( 'code' === $node_name ) {
$inline_content = $this->convert_child_nodes_to_blocks_or_html( $child_node );
$content .= "<code>{$inline_content}</code>";
} else { } else {
$content .= $this->convert_node_to_block( $child_node ); $content .= $this->convert_node_to_block( $child_node );
} }

View File

@ -60,3 +60,35 @@
<!-- wp:paragraph --> <!-- wp:paragraph -->
<p><img src="https://picsum.photos/200/300" alt="An image" /></p> <p><img src="https://picsum.photos/200/300" alt="An image" /></p>
<!-- /wp:paragraph --> <!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>$ cd /path/to/woocommerce-docs
</code></pre>
<!-- /wp:code -->
<!-- wp:quote -->
<blockquote class="wp-block-quote">
<!-- wp:paragraph -->
<p>This is a blockquote.</p>
<!-- /wp:paragraph -->
</blockquote>
<!-- /wp:quote -->
<!-- wp:table -->
<figure class="wp-block-table"><table>
<thead>
<tr>
<th>First Header</th>
<th>Second Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content Cell</td>
<td>Content Cell</td>
</tr>
<tr>
<td>Content Cell</td>
<td>Content Cell</td>
</tr>
</tbody>
</table></figure>
<!-- /wp:table -->

View File

@ -27,3 +27,14 @@ Here is a link: [Woocommerce.com](https://woocommerce.com).
--- ---
![An image](https://picsum.photos/200/300 'This is an image.') ![An image](https://picsum.photos/200/300 'This is an image.')
```
$ cd /path/to/woocommerce-docs
```
> This is a blockquote.
| First Header | Second Header |
| ------------ | ------------- |
| Content Cell | Content Cell |
| Content Cell | Content Cell |

View File

@ -29,3 +29,14 @@ Here is a link: [Woocommerce.com](https://woocommerce.com).
--- ---
![An image](https://picsum.photos/200/300 'This is an image.') ![An image](https://picsum.photos/200/300 'This is an image.')
```
$ cd /path/to/woocommerce-docs
```
> This is a blockquote.
| First Header | Second Header |
| ------------ | ------------- |
| Content Cell | Content Cell |
| Content Cell | Content Cell |