WooCommerce Docs: Improve Manifest Structure, Extend Frontmatter Support (#39214)
This commit is contained in:
parent
66cee083d4
commit
69e9acaba9
|
@ -14,7 +14,8 @@
|
|||
"require-dev": {
|
||||
"woocommerce/woocommerce-sniffs": "^0.1.3",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"yoast/phpunit-polyfills": "^2.0"
|
||||
"yoast/phpunit-polyfills": "^2.0",
|
||||
"php-stubs/wordpress-tests-stubs": "^6.2"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c3e8ed8878c0f36e0b6be7c78d35663f",
|
||||
"content-hash": "061f99e607a2e8a793f0231a294cc761",
|
||||
"packages": [
|
||||
{
|
||||
"name": "dflydev/dot-access-data",
|
||||
|
@ -1030,6 +1030,46 @@
|
|||
},
|
||||
"time": "2022-02-21T01:04:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-stubs/wordpress-tests-stubs",
|
||||
"version": "v6.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-stubs/wordpress-tests-stubs.git",
|
||||
"reference": "175f395c814d9f52ebd2c1c64069a3b01ef764e8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-stubs/wordpress-tests-stubs/zipball/175f395c814d9f52ebd2c1c64069a3b01ef764e8",
|
||||
"reference": "175f395c814d9f52ebd2c1c64069a3b01ef764e8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"php": "~7.3 || ~8.0",
|
||||
"php-stubs/generator": "^0.8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
|
||||
"szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan"
|
||||
},
|
||||
"type": "library",
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "WordPress Tests function and class declaration stubs for static analysis.",
|
||||
"homepage": "https://github.com/php-stubs/wordpress-tests-stubs",
|
||||
"keywords": [
|
||||
"PHPStan",
|
||||
"static analysis",
|
||||
"wordpress"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-stubs/wordpress-tests-stubs/issues",
|
||||
"source": "https://github.com/php-stubs/wordpress-tests-stubs/tree/v6.2.0"
|
||||
},
|
||||
"time": "2023-05-15T07:50:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpcompatibility/php-compatibility",
|
||||
"version": "9.3.5",
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
title: Getting Started with WooCommerce
|
||||
category_title: Getting Started with WooCommerce
|
||||
---
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
post_title: Install the Plugin
|
||||
---
|
||||
|
||||
## Install the plugin
|
||||
|
||||
1. Download the plugin from the [GitHub repository](https://example.com).
|
||||
2. Upload the plugin to your WordPress site.
|
||||
3. Activate the plugin.
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Local Development
|
||||
post_title: Local Development
|
||||
---
|
||||
|
||||
## Local Development
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
title: Troubleshooting Problems
|
||||
category_title: Troubleshooting Problems
|
||||
---
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: What Went Wrong?
|
||||
post_title: What Went Wrong?
|
||||
---
|
||||
|
||||
## Try some troubleshooting
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
title: Testing WooCommerce
|
||||
category_title: Testing WooCommerce
|
||||
---
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Unit Testing
|
||||
post_title: Unit Testing
|
||||
---
|
||||
|
||||
## Unit Test
|
||||
|
|
|
@ -1,39 +1,53 @@
|
|||
{
|
||||
"categories": [
|
||||
{
|
||||
"title": "Getting Started with WooCommerce",
|
||||
"posts": [
|
||||
{
|
||||
"title": "Local Development",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/plugins/woocommerce-docs/example-docs/get-started/local-development.md",
|
||||
"id": "c068ce54044fa44c760a69bd71ef21274f2a5a37"
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"title": "Troubleshooting Problems",
|
||||
"posts": [
|
||||
{
|
||||
"title": "What Went Wrong?",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/plugins/woocommerce-docs/example-docs/get-started/troubleshooting/what-went-wrong.md",
|
||||
"id": "1f88c4d039e72c059c928ab475ad1ea0a02c8abb"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Testing WooCommerce",
|
||||
"posts": [
|
||||
{
|
||||
"title": "Unit Testing",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/plugins/woocommerce-docs/example-docs/testing/unit-tests.md",
|
||||
"id": "120770c899215a889246b47ac883e4dda1f97b8b"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
}
|
||||
],
|
||||
"hash": "180a6ce0bebb8e84072fda451758ef6326490a99e7b3a349b9e45baa8c7c54ac"
|
||||
}
|
||||
"categories": [
|
||||
{
|
||||
"category_title": "Getting Started with WooCommerce",
|
||||
"posts": [
|
||||
{
|
||||
"post_title": "Local Development",
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/plugins/woocommerce-docs/example-docs/get-started/local-development.md",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/plugins/woocommerce-docs/example-docs/get-started/local-development.md",
|
||||
"id": "c068ce54044fa44c760a69bd71ef21274f2a5a37"
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"category_title": "Installation",
|
||||
"posts": [
|
||||
{
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/plugins/woocommerce-docs/example-docs/get-started/installation/install-plugin.md",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/plugins/woocommerce-docs/example-docs/get-started/installation/install-plugin.md",
|
||||
"id": "fb59bd01dda7b090e5b0a557948e155a6b679d6a"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"category_title": "Troubleshooting Problems",
|
||||
"posts": [
|
||||
{
|
||||
"post_title": "What Went Wrong?",
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/plugins/woocommerce-docs/example-docs/get-started/troubleshooting/what-went-wrong.md",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/plugins/woocommerce-docs/example-docs/get-started/troubleshooting/what-went-wrong.md",
|
||||
"id": "1f88c4d039e72c059c928ab475ad1ea0a02c8abb"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category_title": "Testing WooCommerce",
|
||||
"posts": [
|
||||
{
|
||||
"post_title": "Unit Testing",
|
||||
"edit_url": "https://github.com/woocommerce/woocommerce/edit/trunk/plugins/woocommerce-docs/example-docs/testing/unit-tests.md",
|
||||
"url": "https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/plugins/woocommerce-docs/example-docs/testing/unit-tests.md",
|
||||
"id": "120770c899215a889246b47ac883e4dda1f97b8b"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
}
|
||||
],
|
||||
"hash": "db0047299d7dd99bd9a657d59be9e6e4f113710a253c27417427965f7a5ebc8c"
|
||||
}
|
||||
|
|
|
@ -31,6 +31,39 @@ class ManifestProcessor {
|
|||
return $converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate post args
|
||||
*
|
||||
* @param mixed $post The post to generate args for.
|
||||
* @param mixed $post_content The post content.
|
||||
* @return array
|
||||
*/
|
||||
private static function generate_post_args( $post, $post_content ) {
|
||||
$possible_attributes = array(
|
||||
'post_title',
|
||||
'post_author',
|
||||
'post_date',
|
||||
'comment_status',
|
||||
'post_status',
|
||||
);
|
||||
|
||||
$args = array();
|
||||
|
||||
foreach ( $possible_attributes as $attribute ) {
|
||||
if ( isset( $post[ $attribute ] ) ) {
|
||||
$args[ $attribute ] = $post[ $attribute ];
|
||||
}
|
||||
}
|
||||
|
||||
$args['post_content'] = $post_content;
|
||||
|
||||
if ( ! isset( $args['post_status'] ) ) {
|
||||
$args['post_status'] = 'publish';
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process categories
|
||||
*
|
||||
|
@ -40,25 +73,27 @@ class ManifestProcessor {
|
|||
*/
|
||||
private static function process_categories( $categories, $logger_action_id, $parent_id = 0 ) {
|
||||
foreach ( $categories as $category ) {
|
||||
$term = term_exists( $category['title'], 'category' );
|
||||
$term = term_exists( $category['category_title'], 'category' );
|
||||
|
||||
$category_args = array( 'parent' => $parent_id );
|
||||
|
||||
if ( isset( $category['category_slug'] ) ) {
|
||||
$category_args['slug'] = $category['category_slug'];
|
||||
}
|
||||
|
||||
// If the category doesn't exist, create it.
|
||||
if ( 0 === $term || null === $term ) {
|
||||
$term = wp_insert_term(
|
||||
$category['title'],
|
||||
$category['category_title'],
|
||||
'category',
|
||||
array(
|
||||
'parent' => $parent_id,
|
||||
)
|
||||
$category_args
|
||||
);
|
||||
} else {
|
||||
// If the category exists, update it.
|
||||
$term = wp_update_term(
|
||||
$term['term_id'],
|
||||
'category',
|
||||
array(
|
||||
'parent' => $parent_id,
|
||||
)
|
||||
$category_args
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -85,31 +120,27 @@ class ManifestProcessor {
|
|||
// If the post doesn't exist, create it.
|
||||
if ( ! $existing_post ) {
|
||||
$post_id = \WooCommerceDocs\Data\DocsStore::insert_docs_post(
|
||||
array(
|
||||
'post_title' => $post['title'],
|
||||
'post_content' => $blocks,
|
||||
'post_status' => 'publish',
|
||||
),
|
||||
self::generate_post_args( $post, $blocks ),
|
||||
$post['id']
|
||||
);
|
||||
|
||||
\ActionScheduler_Logger::instance()->log( $logger_action_id, 'Created post with id: ' . $post_id );
|
||||
|
||||
} else {
|
||||
|
||||
$post_update = self::generate_post_args( $post, $blocks );
|
||||
$post_update = array_merge( $post_update, array( 'ID' => $existing_post->ID ) );
|
||||
|
||||
// if the post exists, update it .
|
||||
$post_id = \WoocommerceDocs\Data\DocsStore::update_docs_post(
|
||||
array(
|
||||
'ID' => $existing_post->ID,
|
||||
'post_title' => $post['title'],
|
||||
'post_content' => $blocks,
|
||||
),
|
||||
$post_update,
|
||||
$post['id']
|
||||
);
|
||||
|
||||
\ActionScheduler_Logger::instance()->log( $logger_action_id, 'Updated post with id: ' . $post_id );
|
||||
}
|
||||
|
||||
wp_set_post_categories( $post_id, array( $term['term_id'] ), $parent_id );
|
||||
wp_set_post_categories( $post_id, array( $term['term_id'] ) );
|
||||
}
|
||||
|
||||
// Process any sub-categories.
|
||||
|
|
|
@ -11,3 +11,6 @@ $tests_dir = getenv( 'WP_TESTS_DIR' );
|
|||
|
||||
require_once $tests_dir . '/includes/functions.php';
|
||||
require_once $tests_dir . '/includes/bootstrap.php';
|
||||
|
||||
// Require action-scheduler manually.
|
||||
require_once __DIR__ . '/../vendor/woocommerce/action-scheduler/action-scheduler.php';
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace WooCommerceDocs\Tests\Manifest;
|
||||
|
||||
use WooCommerceDocs\Manifest\ManifestProcessor;
|
||||
use WP_UnitTestCase;
|
||||
use WooCommerceDocs\Data\DocsStore;
|
||||
|
||||
/**
|
||||
* Class ManifestProcessorTest
|
||||
*
|
||||
* @package WooCommerceDocs\Tests\Manifest
|
||||
*/
|
||||
class ManifestProcessorTest extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Test processing a manifest into WordPress posts and categories.
|
||||
*/
|
||||
public function test_process_manifest() {
|
||||
|
||||
$manifest = json_decode( file_get_contents( __DIR__ . '/fixtures/manifest.json' ), true );
|
||||
$md_file = file_get_contents( __DIR__ . '/fixtures/test.md' );
|
||||
|
||||
// Mock the wp_remote_get function with a filter.
|
||||
add_filter(
|
||||
'pre_http_request',
|
||||
function ( $preempt, $args, $url ) use ( $md_file ) {
|
||||
return array(
|
||||
'response' => array(
|
||||
'code' => 200,
|
||||
'message' => 'OK',
|
||||
),
|
||||
'body' => $md_file,
|
||||
);
|
||||
},
|
||||
10,
|
||||
3
|
||||
);
|
||||
|
||||
ManifestProcessor::process_manifest( $manifest, 123 );
|
||||
|
||||
$get_started_category = get_term_by( 'name', 'Getting Started with WooCommerce', 'category' );
|
||||
$this->assertNotFalse( $get_started_category );
|
||||
|
||||
$install_category = get_term_by( 'name', 'Installation', 'category' );
|
||||
$this->assertNotFalse( $install_category );
|
||||
// Check parent is correct.
|
||||
$this->assertEquals( $get_started_category->term_id, $install_category->parent );
|
||||
|
||||
$troubleshoot_category = get_term_by( 'name', 'Troubleshooting Problems', 'category' );
|
||||
$this->assertNotFalse( $troubleshoot_category );
|
||||
// Check parent is correct.
|
||||
$this->assertEquals( $get_started_category->term_id, $troubleshoot_category->parent );
|
||||
|
||||
$testing_category = get_term_by( 'name', 'Testing WooCommerce', 'category' );
|
||||
$this->assertNotFalse( $testing_category );
|
||||
|
||||
// check posts exist using the DocStore.
|
||||
$posts = DocsStore::get_posts();
|
||||
$this->assertEquals( 4, count( $posts ) );
|
||||
|
||||
$install_plugin_post = $posts[0];
|
||||
$local_dev_post = $posts[1];
|
||||
$unit_testing_post = $posts[2];
|
||||
$what_went_wrong_post = $posts[3];
|
||||
|
||||
// check doc titles (note that they are returned in alpha order).
|
||||
$this->assertEquals( 'Install the Plugin', $install_plugin_post->post_title );
|
||||
$this->assertEquals( 'Local Development', $local_dev_post->post_title );
|
||||
$this->assertEquals( 'Unit Testing', $unit_testing_post->post_title );
|
||||
$this->assertEquals( 'What Went Wrong?', $what_went_wrong_post->post_title );
|
||||
|
||||
// Assert that post was assigned to categories.
|
||||
$this->assertTrue( has_category( $install_category->term_id, $install_plugin_post->ID ) );
|
||||
$this->assertTrue( has_category( $troubleshoot_category->term_id, $what_went_wrong_post->ID ) );
|
||||
$this->assertTrue( has_category( $testing_category->term_id, $unit_testing_post->ID ) );
|
||||
$this->assertTrue( has_category( $troubleshoot_category->term_id, $what_went_wrong_post->ID ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"categories": [
|
||||
{
|
||||
"category_title": "Getting Started with WooCommerce",
|
||||
"posts": [
|
||||
{
|
||||
"post_title": "Local Development",
|
||||
"edit_url": "https://example.com/edit/local-development.md",
|
||||
"url": "https://example.com/local-development.md",
|
||||
"id": "c068ce54044fa44c760a69bd71ef21274f2a5a37"
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"category_title": "Installation",
|
||||
"posts": [
|
||||
{
|
||||
"post_title": "Install the Plugin",
|
||||
"edit_url": "https://example.com/edit/install-plugin.md",
|
||||
"url": "https://example.com/install-plugin.md",
|
||||
"id": "fb59bd01dda7b090e5b0a557948e155a6b679d6a"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
},
|
||||
{
|
||||
"category_title": "Troubleshooting Problems",
|
||||
"posts": [
|
||||
{
|
||||
"post_title": "What Went Wrong?",
|
||||
"edit_url": "https://example.com/edit/what-went-wrong.md",
|
||||
"url": "https://example.com/what-went-wrong.md",
|
||||
"id": "1f88c4d039e72c059c928ab475ad1ea0a02c8abb"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category_title": "Testing WooCommerce",
|
||||
"posts": [
|
||||
{
|
||||
"post_title": "Unit Testing",
|
||||
"edit_url": "https://example.com/edit/unit-tests.md",
|
||||
"url": "https://example.com/unit-tests.md",
|
||||
"id": "120770c899215a889246b47ac883e4dda1f97b8b"
|
||||
}
|
||||
],
|
||||
"categories": []
|
||||
}
|
||||
],
|
||||
"hash": "db0047299d7dd99bd9a657d59be9e6e4f113710a253c27417427965f7a5ebc8c"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
post_title: Testing Post
|
||||
---
|
||||
|
||||
### Testing Post
|
||||
|
||||
This is a test post.
|
|
@ -3474,6 +3474,9 @@ importers:
|
|||
gray-matter:
|
||||
specifier: ^4.0.3
|
||||
version: 4.0.3
|
||||
js-yaml:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0
|
||||
octokit:
|
||||
specifier: ^2.0.14
|
||||
version: 2.0.14
|
||||
|
@ -9184,8 +9187,8 @@ packages:
|
|||
dependencies:
|
||||
'@babel/core': 7.21.3
|
||||
'@babel/helper-module-imports': 7.16.0
|
||||
'@babel/helper-plugin-utils': 7.14.5
|
||||
babel-plugin-polyfill-corejs2: 0.3.0(@babel/core@7.21.3)
|
||||
'@babel/helper-plugin-utils': 7.21.5
|
||||
babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.3)
|
||||
babel-plugin-polyfill-corejs3: 0.4.0(@babel/core@7.21.3)
|
||||
babel-plugin-polyfill-regenerator: 0.3.0(@babel/core@7.21.3)
|
||||
semver: 6.3.0
|
||||
|
@ -18453,7 +18456,7 @@ packages:
|
|||
'@wordpress/style-engine': 0.15.0
|
||||
'@wordpress/token-list': 2.19.0
|
||||
'@wordpress/url': 3.29.0
|
||||
'@wordpress/warning': 2.34.0
|
||||
'@wordpress/warning': 2.19.0
|
||||
'@wordpress/wordcount': 3.19.0
|
||||
change-case: 4.1.2
|
||||
classnames: 2.3.1
|
||||
|
@ -19813,7 +19816,7 @@ packages:
|
|||
cosmiconfig: 7.0.1
|
||||
eslint: 8.32.0
|
||||
eslint-config-prettier: 8.5.0(eslint@8.32.0)
|
||||
eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.54.0)(eslint-import-resolver-typescript@2.5.0)(eslint-import-resolver-webpack@0.13.2)(eslint@8.32.0)
|
||||
eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.54.0)(eslint@8.32.0)
|
||||
eslint-plugin-jest: 27.2.1(@typescript-eslint/eslint-plugin@5.54.0)(eslint@8.32.0)(jest@27.5.1)(typescript@4.9.5)
|
||||
eslint-plugin-jsdoc: 39.9.1(eslint@8.32.0)
|
||||
eslint-plugin-jsx-a11y: 6.5.1(eslint@8.32.0)
|
||||
|
@ -19854,7 +19857,7 @@ packages:
|
|||
cosmiconfig: 7.0.1
|
||||
eslint: 8.32.0
|
||||
eslint-config-prettier: 8.5.0(eslint@8.32.0)
|
||||
eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.54.0)(eslint-import-resolver-typescript@2.5.0)(eslint-import-resolver-webpack@0.13.2)(eslint@8.32.0)
|
||||
eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.54.0)(eslint@8.32.0)
|
||||
eslint-plugin-jest: 27.2.1(@typescript-eslint/eslint-plugin@5.54.0)(eslint@8.32.0)(jest@27.5.1)(typescript@4.9.5)
|
||||
eslint-plugin-jsdoc: 39.9.1(eslint@8.32.0)
|
||||
eslint-plugin-jsx-a11y: 6.5.1(eslint@8.32.0)
|
||||
|
@ -19895,7 +19898,7 @@ packages:
|
|||
cosmiconfig: 7.0.1
|
||||
eslint: 8.32.0
|
||||
eslint-config-prettier: 8.5.0(eslint@8.32.0)
|
||||
eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.54.0)(eslint-import-resolver-typescript@2.5.0)(eslint-import-resolver-webpack@0.13.2)(eslint@8.32.0)
|
||||
eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.54.0)(eslint@8.32.0)
|
||||
eslint-plugin-jest: 27.2.1(@typescript-eslint/eslint-plugin@5.54.0)(eslint@8.32.0)(jest@29.5.0)(typescript@4.9.5)
|
||||
eslint-plugin-jsdoc: 39.9.1(eslint@8.32.0)
|
||||
eslint-plugin-jsx-a11y: 6.5.1(eslint@8.32.0)
|
||||
|
@ -27112,7 +27115,7 @@ packages:
|
|||
has: 1.0.3
|
||||
is-core-module: 2.8.0
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.0.4
|
||||
minimatch: 3.1.2
|
||||
object.values: 1.1.5
|
||||
resolve: 1.20.0
|
||||
tsconfig-paths: 3.14.0
|
||||
|
@ -27152,6 +27155,36 @@ packages:
|
|||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
/eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.54.0)(eslint@8.32.0):
|
||||
resolution: {integrity: sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.54.0(eslint@8.32.0)(typescript@4.9.5)
|
||||
array-includes: 3.1.4
|
||||
array.prototype.flat: 1.2.5
|
||||
debug: 2.6.9(supports-color@6.1.0)
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.32.0
|
||||
eslint-import-resolver-node: 0.3.6
|
||||
eslint-module-utils: 2.7.3(@typescript-eslint/parser@5.54.0)(eslint-import-resolver-node@0.3.6)(eslint-import-resolver-typescript@2.5.0)(eslint-import-resolver-webpack@0.13.2)
|
||||
has: 1.0.3
|
||||
is-core-module: 2.8.0
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.values: 1.1.5
|
||||
resolve: 1.20.0
|
||||
tsconfig-paths: 3.14.0
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
/eslint-plugin-jest@23.20.0(eslint@7.32.0)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -34072,7 +34105,7 @@ packages:
|
|||
esprima: 4.0.1
|
||||
|
||||
/js-yaml@3.5.3:
|
||||
resolution: {integrity: sha1-6e5ggrBld3DkNG368qWMWZIlH3Y=}
|
||||
resolution: {integrity: sha512-rkxjJUwevxyYOdr45k3IOyZjyhRbEMqUvcMyXXeBXTf8kdFaFKUIvMkdHgIcFIjNIoctM6l/emA7OjXYVabYSw==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
argparse: 1.0.10
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"glob": "^10.2.4",
|
||||
"graphql": "^16.6.0",
|
||||
"gray-matter": "^4.0.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"octokit": "^2.0.14",
|
||||
"ora": "^5.4.1",
|
||||
"promptly": "^3.2.0",
|
||||
|
|
|
@ -38,8 +38,13 @@ export const generateManifestCommand = new Command( 'create' )
|
|||
'Root directory of the markdown files, used to generate URLs.',
|
||||
process.cwd()
|
||||
)
|
||||
.option(
|
||||
'-be --baseEditUrl <baseEditUrl>',
|
||||
'Base url to provide edit links to. This option will be ignored if your baseUrl is not a GitHub URL.',
|
||||
'https://github.com/woocommerce/woocommerce/edit/trunk'
|
||||
)
|
||||
.action( async ( dir, projectName, options ) => {
|
||||
const { outputFilePath, baseUrl, rootDir } = options;
|
||||
const { outputFilePath, baseUrl, rootDir, baseEditUrl } = options;
|
||||
|
||||
// determine if the rootDir is absolute or relative
|
||||
const absoluteRootDir = path.isAbsolute( rootDir )
|
||||
|
@ -60,7 +65,8 @@ export const generateManifestCommand = new Command( 'create' )
|
|||
absoluteRootDir,
|
||||
absoluteSubDir,
|
||||
projectName,
|
||||
baseUrl
|
||||
baseUrl,
|
||||
baseEditUrl
|
||||
);
|
||||
|
||||
Logger.endTask();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
---
|
||||
title: Getting Started with WooCommerce
|
||||
category_title: Getting Started with WooCommerce
|
||||
category_slug: get-started
|
||||
---
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
### Install the plugin
|
||||
|
||||
1. Download the plugin from the [GitHub repository](https://example.com).
|
||||
2. Upload the plugin to your WordPress site.
|
||||
3. Activate the plugin.
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Local Development
|
||||
post_title: Local Development
|
||||
---
|
||||
|
||||
## Local Development
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
title: Troubleshooting Problems
|
||||
category_title: Troubleshooting Problems
|
||||
---
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: What Went Wrong?
|
||||
post_title: What Went Wrong?
|
||||
---
|
||||
|
||||
## Try some troubleshooting
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
title: Testing WooCommerce
|
||||
category_title: Testing WooCommerce
|
||||
---
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Unit Testing
|
||||
category_title: Unit Testing
|
||||
---
|
||||
|
||||
## Unit Test
|
||||
|
|
|
@ -6,7 +6,7 @@ import path from 'path';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { generateFileUrl } from '../generate-manifest';
|
||||
import { generateFileUrl } from '../generate-urls';
|
||||
|
||||
describe( 'generateFileUrl', () => {
|
||||
it( 'should generate a file url relative to the root directory provided', () => {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { generatePostFrontMatter } from '../generate-frontmatter';
|
||||
|
||||
describe( 'generateFrontmatter', () => {
|
||||
it( 'should not allow disallowed attributes', () => {
|
||||
const frontMatter = generatePostFrontMatter( `---
|
||||
title: Hello World
|
||||
description: This is a description
|
||||
post_content: This is some content
|
||||
post_title: This is a title
|
||||
---
|
||||
` );
|
||||
|
||||
expect( frontMatter ).toEqual( {
|
||||
post_title: 'This is a title',
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'should not do additional date parsing', () => {
|
||||
const frontMatter = generatePostFrontMatter( `---
|
||||
post_date: 2023-07-12 15:30:00
|
||||
---
|
||||
` );
|
||||
|
||||
expect( frontMatter ).toEqual( {
|
||||
post_date: '2023-07-12 15:30:00',
|
||||
} );
|
||||
} );
|
||||
} );
|
|
@ -18,31 +18,47 @@ describe( 'generateManifest', () => {
|
|||
rootDir,
|
||||
dir,
|
||||
'example-docs',
|
||||
'https://example.com'
|
||||
'https://example.com',
|
||||
'https://example.com/edit'
|
||||
);
|
||||
|
||||
const topLevelCategories = manifest.categories;
|
||||
|
||||
expect( topLevelCategories[ 0 ].title ).toEqual(
|
||||
expect( topLevelCategories[ 0 ].category_title ).toEqual(
|
||||
'Getting Started with WooCommerce'
|
||||
);
|
||||
expect( topLevelCategories[ 1 ].title ).toEqual(
|
||||
expect( topLevelCategories[ 1 ].category_title ).toEqual(
|
||||
'Testing WooCommerce'
|
||||
);
|
||||
|
||||
const subCategories = topLevelCategories[ 0 ].categories;
|
||||
|
||||
expect( subCategories[ 0 ].title ).toEqual(
|
||||
expect( subCategories[ 1 ].category_title ).toEqual(
|
||||
'Troubleshooting Problems'
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'should create categories with titles where there is no index README', async () => {
|
||||
const manifest = await generateManifestFromDirectory(
|
||||
rootDir,
|
||||
dir,
|
||||
'example-docs',
|
||||
'https://example.com',
|
||||
'https://example.com/edit'
|
||||
);
|
||||
|
||||
expect(
|
||||
manifest.categories[ 0 ].categories[ 0 ].category_title
|
||||
).toEqual( 'Installation' );
|
||||
} );
|
||||
|
||||
it( 'should create post urls with the correct url', async () => {
|
||||
const manifest = await generateManifestFromDirectory(
|
||||
rootDir,
|
||||
dir,
|
||||
'example-docs',
|
||||
'https://example.com'
|
||||
'https://example.com',
|
||||
'https://example.com/edit'
|
||||
);
|
||||
|
||||
expect( manifest.categories[ 0 ].posts[ 0 ].url ).toEqual(
|
||||
|
@ -52,7 +68,7 @@ describe( 'generateManifest', () => {
|
|||
expect(
|
||||
manifest.categories[ 0 ].categories[ 0 ].posts[ 0 ].url
|
||||
).toEqual(
|
||||
'https://example.com/example-docs/get-started/troubleshooting/what-went-wrong.md'
|
||||
'https://example.com/example-docs/get-started/installation/install-plugin.md'
|
||||
);
|
||||
} );
|
||||
|
||||
|
@ -61,9 +77,24 @@ describe( 'generateManifest', () => {
|
|||
rootDir,
|
||||
dir,
|
||||
'example-docs',
|
||||
'https://example.com'
|
||||
'https://example.com',
|
||||
'https://example.com/edit'
|
||||
);
|
||||
|
||||
expect( manifest.hash ).not.toBeUndefined();
|
||||
} );
|
||||
|
||||
it( 'should generate edit_url when github is in the base url', async () => {
|
||||
const manifest = await generateManifestFromDirectory(
|
||||
rootDir,
|
||||
dir,
|
||||
'example-docs',
|
||||
'https://github.com',
|
||||
'https://github.com/edit'
|
||||
);
|
||||
|
||||
expect( manifest.categories[ 0 ].posts[ 0 ].edit_url ).toEqual(
|
||||
'https://github.com/edit/example-docs/get-started/local-development.md'
|
||||
);
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import matter from 'gray-matter';
|
||||
import yaml from 'js-yaml';
|
||||
|
||||
/**
|
||||
* Generate front-matter for supported post attributes.
|
||||
*
|
||||
* @param fileContents
|
||||
*/
|
||||
export const generatePostFrontMatter = (
|
||||
fileContents: string
|
||||
): {
|
||||
[ key: string ]: unknown;
|
||||
} => {
|
||||
const allowList = [
|
||||
'post_date',
|
||||
'post_title',
|
||||
'page_template',
|
||||
'post_author',
|
||||
'post_name',
|
||||
'category_title',
|
||||
'category_slug',
|
||||
];
|
||||
|
||||
const frontMatter = matter( fileContents, {
|
||||
engines: {
|
||||
// By passing yaml.JSON_SCHEMA we disable date parsing that changes date format.
|
||||
// See https://github.com/jonschlinkert/gray-matter/issues/62#issuecomment-577628177 for more details.
|
||||
yaml: ( s ) => yaml.load( s, { schema: yaml.JSON_SCHEMA } ),
|
||||
},
|
||||
} ).data;
|
||||
|
||||
return Object.keys( frontMatter )
|
||||
.filter( ( key ) => allowList.includes( key ) )
|
||||
.reduce( ( obj, key ) => {
|
||||
obj[ key ] = frontMatter[ key ];
|
||||
return obj;
|
||||
}, {} );
|
||||
};
|
|
@ -3,10 +3,15 @@
|
|||
*/
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import matter from 'gray-matter';
|
||||
import { glob } from 'glob';
|
||||
import crypto from 'crypto';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { generatePostFrontMatter } from './generate-frontmatter';
|
||||
import { generateFileUrl } from './generate-urls';
|
||||
|
||||
interface Category {
|
||||
[ key: string ]: unknown;
|
||||
posts?: Post[];
|
||||
|
@ -23,59 +28,28 @@ function generatePageId( filePath: string, prefix = '' ) {
|
|||
return hash.digest( 'hex' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a file url relative to the root directory provided.
|
||||
*
|
||||
* @param baseUrl The base url to use for the file url.
|
||||
* @param rootDirectory The root directory where the file resides.
|
||||
* @param subDirectory The sub-directory where the file resides.
|
||||
* @param absoluteFilePath The absolute path to the file.
|
||||
* @return The file url.
|
||||
*/
|
||||
export const generateFileUrl = (
|
||||
baseUrl: string,
|
||||
rootDirectory: string,
|
||||
subDirectory: string,
|
||||
absoluteFilePath: string
|
||||
) => {
|
||||
// check paths are absolute
|
||||
for ( const filePath of [
|
||||
rootDirectory,
|
||||
subDirectory,
|
||||
absoluteFilePath,
|
||||
] ) {
|
||||
if ( ! path.isAbsolute( filePath ) ) {
|
||||
throw new Error(
|
||||
`File URLs cannot be generated without absolute paths. ${ filePath } is not absolute.`
|
||||
);
|
||||
}
|
||||
}
|
||||
// Generate a path from the subdirectory to the file path.
|
||||
const relativeFilePath = path.resolve( subDirectory, absoluteFilePath );
|
||||
|
||||
// Determine the relative path from the rootDirectory to the filePath.
|
||||
const relativePath = path.relative( rootDirectory, relativeFilePath );
|
||||
|
||||
return `${ baseUrl }/${ relativePath }`;
|
||||
};
|
||||
|
||||
async function processDirectory(
|
||||
rootDirectory: string,
|
||||
subDirectory: string,
|
||||
projectName: string,
|
||||
baseUrl: string,
|
||||
baseEditUrl: string,
|
||||
checkReadme = true
|
||||
): Promise< Category > {
|
||||
let category: Category = {};
|
||||
const category: Category = {};
|
||||
|
||||
// Process README.md (if exists) for the category definition.
|
||||
const readmePath = path.join( subDirectory, 'README.md' );
|
||||
|
||||
if ( checkReadme && fs.existsSync( readmePath ) ) {
|
||||
const readmeContent = fs.readFileSync( readmePath, 'utf-8' );
|
||||
const readmeFrontmatter = matter( readmeContent ).data;
|
||||
category = { ...readmeFrontmatter };
|
||||
category.posts = [];
|
||||
const frontMatter = generatePostFrontMatter( readmeContent );
|
||||
Object.assign( category, frontMatter );
|
||||
} else if ( checkReadme ) {
|
||||
// derive the category title from the directory name, capitalize first letter
|
||||
const categoryTitle = path.basename( subDirectory );
|
||||
category.category_title =
|
||||
categoryTitle.charAt( 0 ).toUpperCase() + categoryTitle.slice( 1 );
|
||||
}
|
||||
|
||||
const markdownFiles = glob.sync( path.join( subDirectory, '*.md' ) );
|
||||
|
@ -84,7 +58,18 @@ async function processDirectory(
|
|||
if ( filePath !== readmePath || ! checkReadme ) {
|
||||
// Skip README.md which we have already processed.
|
||||
const fileContent = fs.readFileSync( filePath, 'utf-8' );
|
||||
const fileFrontmatter = matter( fileContent ).data;
|
||||
const fileFrontmatter = generatePostFrontMatter( fileContent );
|
||||
category.posts = [];
|
||||
|
||||
if ( baseUrl.includes( 'github' ) ) {
|
||||
fileFrontmatter.edit_url = generateFileUrl(
|
||||
baseEditUrl,
|
||||
rootDirectory,
|
||||
subDirectory,
|
||||
filePath
|
||||
);
|
||||
}
|
||||
|
||||
const post: Post = { ...fileFrontmatter };
|
||||
|
||||
category.posts.push( {
|
||||
|
@ -111,7 +96,8 @@ async function processDirectory(
|
|||
rootDirectory,
|
||||
subdirectory,
|
||||
projectName,
|
||||
baseUrl
|
||||
baseUrl,
|
||||
baseEditUrl
|
||||
);
|
||||
|
||||
category.categories.push( subcategory );
|
||||
|
@ -124,13 +110,15 @@ export async function generateManifestFromDirectory(
|
|||
rootDirectory: string,
|
||||
subDirectory: string,
|
||||
projectName: string,
|
||||
baseUrl: string
|
||||
baseUrl: string,
|
||||
baseEditUrl: string
|
||||
) {
|
||||
const manifest = await processDirectory(
|
||||
rootDirectory,
|
||||
subDirectory,
|
||||
projectName,
|
||||
baseUrl,
|
||||
baseEditUrl,
|
||||
false
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import path from 'path';
|
||||
|
||||
/**
|
||||
* Generates a file url relative to the root directory provided.
|
||||
*
|
||||
* @param baseUrl The base url to use for the file url.
|
||||
* @param rootDirectory The root directory where the file resides.
|
||||
* @param subDirectory The sub-directory where the file resides.
|
||||
* @param absoluteFilePath The absolute path to the file.
|
||||
* @return The file url.
|
||||
*/
|
||||
export const generateFileUrl = (
|
||||
baseUrl: string,
|
||||
rootDirectory: string,
|
||||
subDirectory: string,
|
||||
absoluteFilePath: string
|
||||
) => {
|
||||
// check paths are absolute
|
||||
for ( const filePath of [
|
||||
rootDirectory,
|
||||
subDirectory,
|
||||
absoluteFilePath,
|
||||
] ) {
|
||||
if ( ! path.isAbsolute( filePath ) ) {
|
||||
throw new Error(
|
||||
`File URLs cannot be generated without absolute paths. ${ filePath } is not absolute.`
|
||||
);
|
||||
}
|
||||
}
|
||||
// Generate a path from the subdirectory to the file path.
|
||||
const relativeFilePath = path.resolve( subDirectory, absoluteFilePath );
|
||||
|
||||
// Determine the relative path from the rootDirectory to the filePath.
|
||||
const relativePath = path.relative( rootDirectory, relativeFilePath );
|
||||
|
||||
return `${ baseUrl }/${ relativePath }`;
|
||||
};
|
Loading…
Reference in New Issue