Giter Club home page Giter Club logo

vip-governance-plugin's Introduction

WordPress VIP Block Governance plugin

This WordPress plugin adds additional governance capabilities to the block editor. This is accomplished via two dimensions:

  • Insertion: restricts what kind of blocks can be inserted into the block editor. Only what’s allowed can be inserted, and nothing else. This means that even if new core blocks are introduced they would not be permitted.
  • Interaction: This adds the ability to control the styling available for blocks at any level.

We have approached this plugin from an opt-in standpoint. In other words, enabling this plugin without any rules will severely limit the editing experience. The goal is to create a stable editor with new blocks and features being enabled explicitly via rules, rather than implicitly via updates.

This plugin is currently developed for use on WordPress sites hosted on the VIP Platform.

Table of contents

Installation

To use the WordPress VIP Block Governance plugin after activation, skip to Usage.

Install on WordPress VIP

The WordPress VIP Block Governance plugin is authored and maintained by WordPress VIP, and made available to all WordPress sites by VIP MU plugins. Customers who host on WordPress VIP or use vip dev-env to develop locally have access to this plugin automatically. We recommend this activation method for WordPress VIP customers.

Enable the plugin by adding the method shown below to your application's [client-mu-plugins/plugin-loader.php][vip-go-skeleton-plugin-loader-example]:

// client-mu-plugins/plugin-loader.php

\Automattic\VIP\Integrations\activate( 'vip-governance' );

Create this path in your WordPress VIP site if it does not yet exist.

This will automatically install and activate the latest mu-plugins release of the WordPress VIP Block Governance plugin. Remove this line to deactivate the plugin.

Install via ZIP file

The latest version of the plugin can be downloaded from the repository's Releases page. Unzip the downloaded plugin and add it to the plugins/ directory of your site's GitHub repository.

Usage

Your governance rules are saved in governance-rules.json in your private folder. Before diving into how it's used, a quick run down of the schema will shed light on how it works.

Note: The private folder is only supported on VIP sites, or while using vip dev-env locally.

Schema Basics

You can find the schema definition used for the rules here. You can use https://api.wpvip.com/schemas/plugins/governance.json as the schema entry in your rules, to take advantage of code completion in most editors.

We have allowed significant space for customization. This means it is also possible to create unintended rule interactions. We recommend making rule changes one or two at a time to troubleshoot these interactions.

Each rule is an object in an array. The one required property is type, which can be default, role, or postType. Your rules should only have one entry of the default type, as described below, and it is the only type that is required in your rule set.

Rules not of type default require an additional field. These are broken down below, along with examples of their possible values:

Rule Type Required Field Possible Values
role roles name/slug of any default or custom roles
postType postTypes name/slug of any default or custom post types

Each rule can have any one of the following properties.

  • allowedFeatures: This is an array of the features that are allowed in the block editor. This list will expand with time, but we currently support two values: codeEditor (viewing the content of your post as code in the editor) and lockBlocks(ability to lock/unlock blocks that will restrict movement/deletion). If you do not want to enable these features, omit them from the array.
  • blockSettings: These are specific settings related to the styling available for a block. They match the settings available in theme.json under the key blocks. The definition for that can be found here. Unlike theme.json, you can nest these rules under a block name to apply different settings depending on the parent of a particular block.
  • allowedBlocks: These are the blocks allowed to be inserted into the block editor. Additionally, you can use allowedBlocks in blockSettings rules to restrict what blocks can be nested under a parent.

Non-default rule types will be merged with the default rule. This is done intentionally to avoid needless repetition of your default properties. If multiple non-default rule types are provided, they will be applied in the following ascending priority:

  1. Post Type
  2. Role

So if a matching postType and role rule is found, the role rule will be applied, and the postType rule will be ignored. The best analogy is the CSS cascade where more specific rules overwrite less specific rules. We are making a choice that Role-based rules should overwrite Post Type rules. We will introduce a filter in the near future to allow this priority to be customized.

Quick Start

By default, the plugin uses this governance-rules.json. To start using the plugin with your own rules, you'll need to create your own governance-rules.json in your private folder. We recommend duplicating one of the starter rule sets provided below, and adapting it for your needs. In order to take advantage of the rules schema for in-editor support, use https://api.wpvip.com/schemas/plugins/governance.json.

With this default rule set, all blocks and all features are enabled. It is sensible to set your default rule to the settings you want for your least privileged user then add capabilities with role and/or post type-specific rules.

Starter Rule Sets

Below is some rule sets that you can use to build your governance-rules.json. They cover a wide range of use cases.

Default Rule Set

This is the default rule set used by the plugin.

{
  "$schema": "https://api.wpvip.com/schemas/plugins/governance.json",
  "version": "1.0.0",
  "rules": [
    {
      "type": "default",
      "allowedFeatures": [ "codeEditor", "lockBlocks" ],
      "allowedBlocks": [ "*" ]
    }
  ]
}

With this rule set, the following rules will apply:

  • All blocks can be inserted across all the roles.
  • No restrictions apply for what's allowed under a block.
  • The code editor is accessible for everyone.
  • Blocks can be locked and unlocked.

Default Rule Set With Restrictions

This expands the default rule set by adding restrictions for all users and post types.

{
  "$schema": "https://api.wpvip.com/schemas/plugins/governance.json",
  "version": "1.0.0",
  "rules": [
    {
      "type": "default",
      "allowedFeatures": [ "codeEditor", "lockBlocks" ],
      "allowedBlocks": [ "core/group", "core/heading", "core/paragraph", "core/image" ],
      "blockSettings": {
        "core/group": {
          "spacing": {
            "spacingSizes": [
              {
                "size": "clamp(2.5rem, 6vw, 3rem)",
                "slug": "300",
                "name": "12"
              }
            ],
          },
        },
        "core/heading": {
          "color": {
            "palette": [
              {
                "color": "#ff0000",
                "name": "Custom red",
                "slug": "custom-red"
              },
              {
                "color": "#00FF00",
                "name": "Custom green",
                "slug": "custom-green"
              },
              {
                "color": "#FFFF00",
                "name": "Custom yellow",
                "slug": "custom-yellow"
              }
            ],
            "gradients": [
              {
                "slug": "vertical-red-to-green",
                "gradient": "linear-gradient(to bottom,#ff0000 0%,#00FF00 100%)",
                "name": "Vertical red to green"
              }
            ]
          },
          "typography": {
            "fontFamilies": [
              {
                "fontFamily": "Consolas, Fira Code, monospace",
                "slug": "code-font",
                "name": "Code Font"
              }
            ],
            "fontSizes": [
              {
                "name": "Large",
                "size": "2.75rem",
                "slug": "large"
              },
              {
                "name": "X-Large",
                "size": "3.75rem",
                "slug": "x-large"
              }
            ]
          }
        }
      }
    }
  ]
}

With this rule set, the following rules will apply:

  • Default: Rules that apply to everyone as a baseline:
    • The only blocks allowed are group, heading, paragraph and image. Under the group block, only heading, paragraph, image and group can be inserted.
    • The code editor is accessible, and blocks can be locked/unlocked or moved.
    • For a heading at the root level, there are 3 custom colors as well as a custom gradient that will show up in the color palette. In addition, a custom font called Code Font as well as 2 custom font sizes will show up in the typography panel.
    • For a group block, there will be only one option for a spacing size available in padding/margin and block spacing.

Default and User Role Rule Set

This example focuses on providing a restrictive default rule set, and expanded permissions for a specific user role.

{
  "$schema": "https://api.wpvip.com/schemas/plugins/governance.json",
  "version": "1.0.0",
  "rules": [
    {
      "type": "role",
      "roles": [ "administrator" ],
      "allowedFeatures": [ "codeEditor", "lockBlocks" ],
      "allowedBlocks": [ "core/quote", "core/media-text", "core/image" ],
      "blockSettings": {
        "core/media-text": {
          "core/heading": {
            "color": {
              "text": true,
              "palette": [
                {
                  "color": "#ff0000",
                  "name": "Custom red",
                  "slug": "custom-red"
                }
              ]
            }
          }
        },
        "core/quote": {
          "core/paragraph": {
            "color": {
              "text": true,
              "palette": [
                {
                  "color": "#00FF00",
                  "name": "Custom green",
                  "slug": "custom-green"
                }
              ]
            }
          }
        }
      }
    },
    {
      "type": "default",
      "allowedBlocks": [ "core/heading", "core/paragraph" ],
      "blockSettings": {
        "core/heading": {
          "color": {
            "text": true,
            "palette": [
              {
                "color": "#FFFF00",
                "name": "Custom yellow",
                "slug": "custom-yellow"
              }
            ]
          }
        }
      }
    }
  ]
}

With this rule set, the following rules will apply:

  • Default: Rules that apply to everyone as a baseline:
    • Heading/paragraph blocks are allowed
    • For a heading at the root level, a custom yellow color will appear as a possible text color option.
    • Blocks cannot be locked/unlocked or moved.
    • The code editor is not accessible.
  • Administrator role: Role-specific rules combined with the default set of rules:
    • In addition to the default allowed blocks, quote/media-text and image blocks are allowed as well. Both the quote, and media-text blocks are allowed to have heading, paragraph, and image blocks inserted under it.
    • A heading at the root level is a custom yellow color as a possible text color option.
    • A heading inside a media-text is allowed to have a custom red color.
    • A paragraph inside a quote is allowed to have a custom green color.
    • The code editor is accessible.
    • Blocks can be locked, unlocked, and moved.

Default and Post Type Rule Set

This example focuses on providing a restrictive default rule set, and expanded permissions for a specific post type.

{
  "$schema": "https://api.wpvip.com/schemas/plugins/governance.json",
  "version": "1.0.0",
  "rules": [
    {
      "type": "postType",
      "postTypes": [ "post" ],
      "allowedFeatures": [ "lockBlocks" ],
      "allowedBlocks": [ "core/quote", "core/image" ],
      "blockSettings": {
        "core/quote": {
          "allowedBlocks": [ "core/paragraph", "core/heading" ],
          "core/paragraph": {
            "color": {
              "text": true,
              "palette": [
                {
                  "color": "#00FF00",
                  "name": "Custom green",
                  "slug": "custom-green"
                }
              ]
            }
          }
        }
      }
    },
    {
      "type": "default",
      "allowedFeatures": [ "codeEditor" ],
      "allowedBlocks": [ "core/heading", "core/paragraph" ],
      "blockSettings": {
        "core/heading": {
          "color": {
            "text": true,
            "palette": [
              {
                "color": "#FFFF00",
                "name": "Custom yellow",
                "slug": "custom-yellow"
              }
            ]
          }
        }
      }
    }
  ]
}

With this rule set, the following rules will apply:

  • Default: Rules that apply to everyone as a baseline:
    • Heading/paragraph blocks are allowed
    • For a heading at the root level, a custom yellow color will appear as a possible text color option.
    • Blocks cannot be locked/unlocked or moved.
    • The code editor is accessible.
  • Posts: Post specific rules combined with the default set of rules:
    • In addition to the default allowed blocks, quote and image blocks are allowed as well. A quote block is allowed to have heading, paragraph and if cascading mode is enabled then an image block as well.
    • A heading at the root level is a custom yellow color as a possible text color option.
    • A paragraph inside a quote is allowed to have a custom green color.
    • The code editor is accessible.
    • Blocks can be locked, unlocked and moved.

Limitations

  • We highly recommend including core/paragraph in allowedBlocks for the default rule so that all users have access to use paragraph blocks. There are some limitations with the editor that make this necessary:

    • The Gutenberg editor uses core/paragraph blocks as an insertion primitive. If a user is unable to insert paragraph blocks, then they will also be unable to insert any other block in the same place.
    • Some core blocks automatically insert core/paragraph blocks that can not be blocked by plugin code. For example, the core/quote block has a child core/paragraph block built-in to block output. Even if a user has core/paragraph blocks disabled, they may still be able to access built-in child blocks.

    It is possible to disable core/paragraph blocks for a role if it makes sense for your workflow but keep in mind these limitations when doing so.

  • Support for color.duotone has not been implemented.

  • wp-env.json within this plugin is intended for tests only, it doesn't work locally.

Code Filters

There are filters in place that can be applied to change the behavior for what's allowed and what's not allowed.

vip_governance__governance_file_path

Change the governance rules file that's used by the plugin, based on a variety of filter options that are available. By default, it is set to the path to governance-rules.json in the private directory in a VIP site. For non-vip sites, it is set to the path to governance-rules.json in the plugin directory.

/**
 * Filter the governance file path, based on the filter options provided.
 * 
 * Currently supported keys:
 * 
 * site_id: The site ID for the current site.
 * 
 * @param string $governance_file_path Path to the governance file.
 * @param array $filter_options Options that can be used as a filter for determining the right file.
 */
apply_filters( 'vip_governance__governance_file_path', $governance_file_path, $filter_options );

For example, this filter can be used to customize the rules file used for a subsite:

add_filter( 'vip_governance__governance_file_path', function ( $governance_file_path, $filter_options ) {
      if ( isset( $filter_options['site_id'] ) && $filter_options['site_id'] === 2 ) {
        return WPCOM_VIP_PRIVATE_DIR . '/site' . '/' . '2/' . WPCOMVIP_GOVERNANCE_RULES_FILENAME;
      }
		  return $governance_file_path;
		}, 10, 2 );

vip_governance__is_block_allowed_for_insertion

Change what blocks are allowed to be inserted in the block editor. By default, root level and children blocks are compared against the governance rules, and then a decision is made to allow or reject them. This filter will allow you to override the default logic for insertion.

/**
 * Change what blocks are allowed to be inserted in the block editor.
 *
 * @param {bool}     isAllowed        Whether or not the block will be allowed.
 * @param {string}   blockName        The name of the block to be inserted.
 * @param {string[]} parentBlockNames An array of zero or more parent block names,
 *                                    starting with the most recent parent ancestor.
 * @param {Object}   governanceRules  An object containing the full set of governance
 *                                    rules for the current user.
 */
return applyFilters(
    'vip_governance__is_block_allowed_for_insertion',
    isAllowed,
    blockType.name,
    parentBlockNames,
    governanceRules
);

For example, this filter can be used to allow the insertion of a custom block even if it's not allowed by the governance rules:

addFilter(
    'vip_governance__is_block_allowed_for_insertion',
    'example/allow-custom-block-insertion',
    ( isAllowed, blockName, parentBlockNames, governanceRules ) => {
        if ( blockName === 'custom/my-amazing-block' ) {
            return true;
        }

        return isAllowed;
    }
);

vip_governance__is_block_allowed_for_editing

Change what blocks are allowed to be edited in the block editor. Disabled blocks will display with a grey border and will not be editable. By default, root level and children blocks are compared against the governance rules, and then a decision is made to allow or reject them. This filter will allow you to override the default logic for editing.

/**
 * Change what blocks are allowed to be edited in the block editor.
 *
 * @param {bool}     isAllowed        Whether or not the block will be allowed.
 * @param {string}   blockName        The name of the block to be edited.
 * @param {string[]} parentBlockNames An array of zero or more parent block names,
 *                                    starting with the most recent parent ancestor.
 * @param {Object}   governanceRules  An object containing the full set of governance
 *                                    rules for the current user.
 */
applyFilters(
    'vip_governance__is_block_allowed_for_editing',
    isAllowed,
    blockName,
    parentBlockNames,
    governanceRules
);

For example, this filter can be used to allow the editing of a custom block type even if it is disabled by governance rules:

addFilter(
    'vip_governance__is_block_allowed_for_editing',
    'example/allow-custom-block-editing',
    ( isAllowed, blockName, parentBlockNames, governanceRules ) => {
        if ( blockName === 'custom/my-amazing-block' ) {
            return true;
        }

        return isAllowed;
    }
);

vip_governance__is_block_allowed_in_hierarchy

Select the mode that's used for determining if a block should be allowed or not, between cascading and restrictive. Cascading works similarly to CSS in that, the rules of the parent are looked up first, followed by the root-level rules for determining if the block is to be allowed or not. On the other hand, restrictive only looks up the rules under the parent. If there are no rules under a parent or a block is not allowed under a parent, then that block cannot be inserted. Cascading allows for a simpler rule file avoiding excessive repetition of blocks under a parent. Restrictive does result in more repetition in the rules file, but it results in a more locked-down editor experience. By default, the filter is set to cascading mode. Note that, you have access to the parent block names, block name, and the governance rules in order to decide what mode should be used. So you can fine tune the mode based on any of these values.

/**
 * Select the mode used to determine if a block should be allowed or not, between cascading and restrictive.
 *
 * @param {bool}                      True, if cascading mode is to be used or false if restrictive is to be used.
 * @param {string}   blockName        The name of the block to be edited.
 * @param {string[]} parentBlockNames An array of zero or more parent block names,
 *                                    starting with the most recent parent ancestor.
 * @param {Object}   governanceRules  An object containing the full set of governance
 *                                    rules for the current user.
 */
  applyFilters(
    'vip_governance__is_block_allowed_in_hierarchy',
    true,
    blockName,
    parentBlockNames,
    governanceRules
  );

Admin Settings

There is an admin settings menu titled VIP Block Governance that's created with the use of this plugin. This page offers:

  • Turning on and off the plugin quickly, without re-deploying.
  • View all the rules at once, and also any errors if the schema is invalid.
  • View combined rules as a specific user role and/or for a specific post type.

Admin setting in action

Endpoints

vip-governance/v1/<role>/rules

This endpoint is used to return the combined rules for a given role. This API is utilized by the settings page to visualize merged default and role rules for a selected role. It's only available to users with the manage_options permission.

It has only three root level keys: allowedBlocks, blockSettings, and allowedFeatures.

Example

This example involves making a call to http://my.site/wp-json/vip-governance/v1/editor/rules for an editor role, while using this rule file found in the starter rule sets:

{
  "allowedBlocks": [ "core/heading", "core/paragraph" ],
  "blockSettings": {
    "core/heading": {
      "color": {
        "text": true,
        "palette": [
          {
            "color": "#FFFF00",
            "name": "Custom yellow",
            "slug": "custom-yellow"
          }
        ]
      }
    }
  },
  "allowedFeatures": []
}

Analytics

Please note this is for VIP sites only. Analytics are disabled if this plugin is not being run on VIP sites.

The plugin records two data points for analytics, on VIP sites:

  1. A usage metric when the block editor is loaded with the WordPress VIP Block Governance plugin activated. This analytic data simply is a counter, and includes no information about the post's content or metadata. It will only include the customer site ID to associate the usage.

  2. When an error occurs from within the plugin on the WordPress VIP platform. This is used to identify issues with customers for private follow-up.

Both of these data points are a counter that is incremented and do not contain any other telemetry or sensitive data. You can see what's being collected in code here.

Development

In order to ensure no dev dependencies are installed, the following can be done while installing the packages:

composer install --no-dev

Tests

We currently have unit, and e2e tests to ensure thorough code coverage of the plugin. These tests can be run locally with wp-env and Docker.

For the PHP unit tests:

wp-env start
composer install
composer run test

For the JS unit tests:

npm install
npm run test:js

For the e2e tests:

wp-env start
composer install
npm install
npx playwright install chromium --with-deps
npx playwright test

vip-governance-plugin's People

Contributors

alecgeatches avatar ingeniumed avatar marijnvdwerf avatar smithjw1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

marijnvdwerf

vip-governance-plugin's Issues

Explore switching to Typescript

This one applies to the Governance Plugin. We should switch to using Typescript so it's consistent with the rest of VIP and also because Typescript is better.

Add filter to enable for programmatic JSON generation.

Currently, all rules are loaded via a file. This prevents more dynamic rule generation.

Could a filter be added so that rules loaded via the file could be augmented by programmatically generated JSON? Or file based loading skipped entirely if programmatic generation is in use?

Incorporate useBlockEditingMode() for block locking

Since useblockEditingMode() has been made public, we should incorporate this in as a replacement for our block locking code in block-locking.jsx.

The strategy would be that:

  • If this method exists, then we should make a call to useBlockEditingMode( 'disabled' ) prior to wrapping the block in the disabled tag.
  • We may need to see if our existing block-locking.php code is still needed or not.

It's already in Gutenberg 16.5 and will be in WordPress 6.4.

Add starter tests for javascript code

The javascript code is currently not tested, we should add tests for that. This issue is meant to get the framework in place and add some starter tests.

We can start with block-utils as that's simple.

Add tracks

Integrate tracks into the plugin so we can record metrics and other data points that we consider important.

Open Question - since this is a beta, should opt out be offered?

Verify Duotone support

Duotone support seems to be done via another function that we don't cover at the moment. This is a property that we haven't tested afaik, so we should verify this and add it to the limitations in the README.

Add support for automated styling

Currently, the plugin just customizes the settings that could be applied to a block. It doesn't automatically apply them when the editor is loaded via styles. This is meant to explore that, so that we can enable post/role based styling in the same way that we can do it via settings. This would open the door to nested styling via role/post type rules.

Handle multisite support

Currently, it's not possible to customize the rules per network site as it's the same private directory for all of them. We should offer a way to customize this, and this could potentially be used then by those not using the plugin on VIP as well.

Improve error messages

In governance error handling code, we have two phases:

  1. Verify that the JSON passes validation
  2. Verify that the JSON matches the schema

While the schema validation is helpful, it still can miss logic errors or produce hard-to-understand errors. For example, if we have a malformed rule like:

{
    "type": "role"
}

We'll show this error:

Schema validation failed: {
    "/rules/2/type": "The data should match one item from enum",
    "/rules/2": "The required properties (roles) are missing"
}

It's not very clear. When we previously used min/max properties, we'd show this instead:

Schema validation failed: {
    "/rules/2": "Object must have at least 2 properties, 1 found"
}

This catches a wider group of error types, but does not explaining what's needed or missing clearly.


I propose we add a layer of rule checking between steps 1 & 2 outlined at the top, where we check rules for logic errors and return clear error messages. This would allow us to produce better error messages than our schema checker can make, and also catch logic errors that might not be possible to encode via schema.

Add unit tests

Add more unit tests for all the code that has no tests

Handle disabling non-theme colours

Currently, we don't hide the non-theme colours shown to the user when we override what style option is available. We should look into customizing that so that only our option is available, or we mention as a README note to follow.

Problems allowing core/list nested in a block

While reviewing the changes in #24, I ran into an issue allowing a user to edit a core/list block within another block. The screenshots in this issue reference PR 24, but that's likely not relevant to the problem.

core/list at the root level

First, let's start with a basic set of locked-down rules that allow an editor to edit a handful of root blocks including core/list and core/list-item:

{
    "$schema": "./governance-schema.json",
    "version": "0.2.0",
    "rules": [
        {
            "type": "default",
            "allowedFeatures": [],
            "allowedBlocks": [ "core/paragraph" ]
        },
        {
            "type": "role",
            "roles": [ "editor" ],
            "allowedBlocks": [ "core/media-text", "core/heading", "core/list", "core/list-item" ],
            "blockSettings": {}
        }
    ]
}

This works fine! Lists can be inserted easily at the root level:

root-level-list

core/list in a core/media-text

Next, let's change the editor role rule. We'll move core/list so that it's the only allowed block in a core/media-text instead. The goal is that we allow core/media-text blocks at the root level, and inside core/media-text blocks we only allow lists.

"rules": [
    {
        "type": "default",
        "allowedFeatures": [],
        "allowedBlocks": [ "core/paragraph" ]
    },
    {
        "type": "role",
        "roles": [ "editor" ],
        "allowedBlocks": [ "core/media-text", "core/heading" ],
        "blockSettings": {
            "core/media-text": {
                "allowedBlocks": [ "core/list" ]
            }
        }
    }
]

This unfortunately doesn't work because the content portion of core/media-text is a core/paragraph, and that's not editable:

core-list-no-paragraph

It seems strange that the default rule core/paragraph doesn't apply here. It may be worth evaluating whether default blocks should be included automatically in allowedBlocks, since I'll need to re-add core/paragraph to any nested block settings. But for now, that's fine, I'll add the paragraph block it to core/media-text's allowedBlocks:

core/list in a core/media-text - Attempt 2

{
    "type": "role",
    "roles": [ "editor" ],
    "allowedBlocks": [ "core/media-text", "core/heading" ],
    "blockSettings": {
        "core/media-text": {
            "allowedBlocks": [ "core/list", "core/paragraph" ]
        }
    }
}

This fixes the content paragraph issue but unfortunately I can't interact with the list item:

core-list-item-blocked

This appears to be because core/list-item isn't allowed. This may be another potential area of improvement. Some blocks like core/list or core/columns are only usable with their child blocks enabled. Potentially we can hardcode some core blocks to support necessary child items to remove this responsibility from the rules file creator.

Anyway, let's add core/list-item support to core/media-text and try that:

core/list in a core/media-text - Attempt 3

{
    "type": "role",
    "roles": [ "editor" ],
    "allowedBlocks": [ "core/media-text", "core/heading" ],
    "blockSettings": {
        "core/media-text": {
            "allowedBlocks": [ "core/paragraph", "core/list", "core/list-item" ]
        }
    }
}

Nope, this still won't let me interact with the list item:

list-item-in-media-text

This is surprising - this same set of allowedBlocks works fine at the root level for inserting core/list-items, but not in core/media-text. I'll try explicitly making a nested rule for core/list:

core/list in a core/media-text - Attempt 4

{
    "type": "role",
    "roles": [ "editor" ],
    "allowedBlocks": [ "core/media-text", "core/heading" ],
    "blockSettings": {
        "core/media-text": {
            "allowedBlocks": [ "core/paragraph", "core/list" ],
            "core/list": {
                "allowedBlocks": [ "core/list-item" ]
            }
        }
    }
}

Still doesn't work, same result as above. Maybe I need to add core/paragraph to the core/list rules too?

core/list in a core/media-text - Attempt 5

{
    "type": "role",
    "roles": [ "editor" ],
    "allowedBlocks": [ "core/media-text", "core/heading" ],
    "blockSettings": {
        "core/media-text": {
            "allowedBlocks": [ "core/paragraph", "core/list" ],
            "core/list": {
                "allowedBlocks": [ "core/paragraph", "core/list-item" ]
            }
        }
    }
}

That didn't do it either, same result as before:

media-text-list-item

I can't find a way to make the original rule idea work:

The goal is that we allow core/media-text blocks at the root level, and inside core/media-text blocks we only allow lists.

Conclusion

There are a few potential issues here:

  1. First and most importantly, I'm not sure how to make a ruleset work where I allow core/list nested in a block and can interact with it's children core/list-item blocks. I can only apply these rules at the root level, but not in a nested block. This seems like a bug, or I'm missing a configuration step.

  2. From "Attempt 1" above:

    It seems strange that the default rule core/paragraph doesn't apply here. It may be worth evaluating whether default blocks should be included automatically in allowedBlocks, since I'll need to re-add core/paragraph to any nested block settings.

    Our default ruleset makes it easy to avoid repeating rules like core/paragraph everywhere, but it only applies to the root set of blocks. Once we start making inner allowedBlocks, we're still required to repeat that. We should consider solutions where that isn't necessary.

  3. From "Attempt 2":

    This may be another potential area of improvement. Some blocks like core/list or core/columns are only usable with their child blocks enabled. Potentially we can hardcode some core blocks to support necessary child items to remove this responsibility from the rules file creator.

    This would ease some of the difficulty of dealing with fiddly inner allowedBlocks rules for some block types.

  4. From "Attempt 3":

    This is surprising - this same set of allowedBlocks works fine at the root level for inserting core/list-items, but not in core/media-text.

    The surprising bit here is that this set of rules works fine, and allows me to insert core/list-items in core/media-text:

    {
        "type": "role",
        "roles": [ "editor" ],
        "allowedBlocks": [ "core/media-text", "core/list", "core/list-item" ]
    }

    However, this set doesn't work, with the same rules applied at the core/media-text block level:

    {
        "type": "role",
        "roles": [ "editor" ],
        "allowedBlocks": [ "core/media-text" ],
        "blockSettings": {
            "core/media-text": {
                "allowedBlocks": [ "core/paragraph", "core/list", "core/list-item" ]
            }
        }
    }

    Root-level allowedBlocks apply to children blocks, but inner allowedBlocks appear to not. This feels inconsistent.

Discussion: Non-WordPress VIP Support

Hi Gopal—Thanks so much for all your work on this plugin!

I'm not sure whether this is the best place for these questions, but I also wasn't sure where else to ask them.

In terms of supporting non-WordPress VIP usage, do you have any plans to:

  • Host the plugin on the WordPress.org Plugin Directory?
  • Allow users to customize a location for the governance-rules.json file (or to create a default location outside of the plugin itself for non-VIP users)?

In terms of the location for the governance-rules.json file: Do you feel the file needs to be kept private for security reasons, or is the WordPress VIP private folder just the most straightforward place for WordPress VIP users to put their own copy?

Thank you again!

Add e2e condition that verifies colours

Add a new e2e test that creates a heading, and a heading within a media text. It then verifies the custom colour yellow for a heading at the root level, and red within a media text.

The following update needs to be made to the wp-env.json to ensure the right rules file is loaded. There is a bug which needs to be solved which is the js/css code we want to load doesn't load. Its likely because the path is off for the plugin dir.

{
	"plugins": [ "." ],
	"mappings": {
		"wp-content/plugins/vip-governance": ".",
		"wp-content/private": "./tests/private"
	},
	"config": {
		"WPCOM_VIP_PRIVATE_DIR": "/var/www/html/wp-content/private"
	}
}

Create a CLI validate command for the rules file

Create a validate CLI command that can be used to quickly confirm if a rules file is correct or not. This could provide a list of core blocks that won't be supported and any potential pitfalls that could come from this.

Use a better solution for determining core nested blocks

The current approach to allowing critical core blocks is via a hardcoded map. There is a way to access the allowedBlocks property in the innerBlocks using the following command:

wp.data.select( 'core/block-editor' ).getAllowedBlocks('49abcad4-4be5-46d0-8db5-44760f15e0e7')

Using this in code causes a call stack exceeded. If this works, this would be a better solution long term.

Check parent-child hierarchy at all depths

This is the TODO from block-utils.js code that wasn't documented in the limitations in the README.

For block searches within a child we only go one level in the parent-child hierarchy in the governance rules.

This is not interpreted correctly that means.

{
    "type": "role",
    "roles": [ "editor" ],
    "allowedBlocks": [ "core/media-text", "core/heading" ],
    "blockSettings": {
        "core/media-text": {
            "allowedBlocks": [ "core/paragraph", "core/list" ],
            "core/list": {
                "allowedBlocks": [ "core/paragraph", "core/list-item" ]
            }
        }
    }
}

Automate the release process

We have too many manual steps for creating a release in RELEAE.md, and we should automate that. Gutenberg can be used as an example for how to do this.

Skip insecure settings

Unlike Gutenberg, we don't currently skip over insecure settings and css values. We should be doing that to ensure we don't create a security problem.

This would be really doing what class-wp-theme-json-gutenberg#remove_insecure_settings does.

Add duotone support

Since we have verified that duotone support is not there, this has been made to add that in. What needs to be done is that, CSS has to be injected onto the page to get duotone values as styles that can be applied.

Disallowed/locked blocks trigger browser console warning

Describe the bug
When opening a post that has illegal blocks, the following warning appeared:

Warning

Unsupported style property background-color. Did you mean backgroundColor?

Seems to be related to this line:

<div style={ { opacity: 0.6, 'background-color': '#eee', border: '2px dashed #999' } }>

To Reproduce

  • Add a block, disallow it in governance.json, reload the post

Expected behavior
No warnings in console

Actual behavior
Warnings in console

Version of the plugin
1.0.6

Additional context

react-dom.js?ver=18.2.0:73 Warning: Unsupported style property background-color. Did you mean backgroundColor?
    at div
    at div
    at Disabled (https://testsite.lndo.site/wp-includes/js/dist/components.js?ver=9a812780592a1d78379b:61076:3)
    at https://testsite.lndo.site/wp-content/plugins/vip-governance/build/index.js?ver=289fda8f4f8dd70bdba8:1:3203
    at FilteredComponentRenderer (https://testsite.lndo.site/wp-includes/js/dist/components.js?ver=9a812780592a1d78379b:75975:9)
    at EditWithGeneratedProps (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:16549:5)
    at BlockEdit (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:16604:5)
    at BlockCrashBoundary (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:16932:5)
    at BlockListBlock (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:18190:10)
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:15699:5
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:32182:5
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:33391:5
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:34958:21
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:37068:112
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:37911:67
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:38389:5
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:38705:5
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:38779:5
    at FilteredComponentRenderer (https://testsite.lndo.site/wp-includes/js/dist/components.js?ver=9a812780592a1d78379b:75975:9)
    at https://testsite.lndo.site/wp-includes/js/dist/compose.js?ver=228e7d7fccaae67c220c:3232:10
    at https://testsite.lndo.site/wp-includes/js/dist/data.js?ver=2b5bb06caaeb5048ed96:4436:25
    at https://testsite.lndo.site/wp-includes/js/dist/data.js?ver=2b5bb06caaeb5048ed96:4286:22
    at shouldComponentUpdate (https://testsite.lndo.site/wp-includes/js/dist/compose.js?ver=228e7d7fccaae67c220c:3268:12)
    at Items (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:28529:3)
    at BlockListItems
    at div
    at Root (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:28447:3)
    at BlockList
    at RecursionProvider (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:56320:3)
    at div
    at WritingFlow (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:20399:3)
    at ExperimentalBlockCanvas (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:41821:3)
    at div
    at MotionComponent (https://testsite.lndo.site/wp-includes/js/dist/components.js?ver=9a812780592a1d78379b:18531:46)
    at div
    at MotionComponent (https://testsite.lndo.site/wp-includes/js/dist/components.js?ver=9a812780592a1d78379b:18531:46)
    at div
    at BlockTools (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:55870:3)
    at VisualEditor (https://testsite.lndo.site/wp-includes/js/dist/edit-post.js?ver=57aa460a64bb0e4ae963:3929:3)
    at div
    at NavigableRegion (https://testsite.lndo.site/wp-includes/js/dist/edit-post.js?ver=57aa460a64bb0e4ae963:1391:3)
    at div
    at div
    at div
    at InterfaceSkeleton (https://testsite.lndo.site/wp-includes/js/dist/edit-post.js?ver=57aa460a64bb0e4ae963:1457:3)
    at Layout (https://testsite.lndo.site/wp-includes/js/dist/edit-post.js?ver=57aa460a64bb0e4ae963:8679:63)
    at ErrorBoundary (https://testsite.lndo.site/wp-includes/js/dist/editor.js?ver=09660a848fa8379476ab:5911:5)
    at BlockRefsProvider (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:17776:3)
    at Provider (https://testsite.lndo.site/wp-includes/js/dist/components.js?ver=9a812780592a1d78379b:36533:3)
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:19222:5
    at https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:18775:5
    at WithRegistryProvider(Component)
    at BlockContextProvider (https://testsite.lndo.site/wp-includes/js/dist/block-editor.js?ver=0930e041f64667e446db:16486:3)
    at EntityProvider (https://testsite.lndo.site/wp-includes/js/dist/core-data.js?ver=77370c9a15a7db2ae084:6359:3)
    at EntityProvider (https://testsite.lndo.site/wp-includes/js/dist/core-data.js?ver=77370c9a15a7db2ae084:6359:3)
    at https://testsite.lndo.site/wp-includes/js/dist/editor.js?ver=09660a848fa8379476ab:12496:3
    at https://testsite.lndo.site/wp-includes/js/dist/editor.js?ver=09660a848fa8379476ab:12081:5
    at WithRegistryProvider(Component)
    at SlotFillProvider (https://testsite.lndo.site/wp-includes/js/dist/components.js?ver=9a812780592a1d78379b:36376:3)
    at provider_SlotFillProvider (https://testsite.lndo.site/wp-includes/js/dist/components.js?ver=9a812780592a1d78379b:36398:5)
    at Provider (https://testsite.lndo.site/wp-includes/js/dist/components.js?ver=9a812780592a1d78379b:36533:3)
    at Editor (https://testsite.lndo.site/wp-includes/js/dist/edit-post.js?ver=57aa460a64bb0e4ae963:9253:3)

Expand rules to be post type specific

This comes from feedback provided by a customer.

We should allow restricting different sets of allowed blocks based on the post type in addition to what we allow right now.

Assets get enqueued with invalid URL on non-VIP deployments

Describe the bug
Frontend assets are enqueued with a path that can result in a 404 (.e.g http://localhost:8080/var/www/html/wp-content/plugins/vip-governance/css/vip-governance.css?ver=1.0.5)

To Reproduce
Install the plugin on a docker container running wordpress:6.4-php8.2.

Expected behavior
Assets get pushed as wp-content/plugins/vip-governance/css/vip-governance.css?ver=1.0.5

Actual behavior
Assets get pushed as http://localhost:8080/var/www/html/wp-content/plugins/vip-governance/css/vip-governance.css?ver=1.0.5

Version of the plugin
1.0.5

Additional context
Replacing some uses of WPCOMVIP_GOVERNANCE_ROOT_PLUGIN_DIR with plugin_dir_url(WPCOMVIP_GOVERNANCE_ROOT_PLUGIN_FILE) resolved the issue.

Block recovery errors in WordPress 6.4

Due to lodash not being enqueued by default anymore in WordPress 6.4, there are block recovery errors happening when trying to select some nested settings in the editor.

The solution is to either enqueue lodash, or use a native alternative to get that we use to fetch the setting at any depth based on the path provided.

Make vendor changes easy

Our development workflow atm is not the best when it comes to vendor changes. We need to ensure we run composer install --no-dev for most cases but for development we need to run composer install. This means that for husky to work we have to be mindful of which one we ran and ensure we do not accidentally check in the test pieces.

There has to be a better way to do this, and we should find that. Simplify the overall workflow.

Add e2e tests

This has been created to write e2e tests using playwright, that will allow us to actually verify that the plugin works within the editor.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.