Add support for wildcard rules in block settings#85
Conversation
|
From an initial runthrough of the code, this looks good! My only thought prior to the full PR would be to change "regex" to "wildcard" in the PR title and internal functions. We don't actually support regular expressions here (which I think is a good thing), just wildcards. I think we should use the term "wildcard" consistently to avoid confusion. |
|
|
||
| ( { value: result } = getNestedSetting( blockNamePath, path, nestedSettings ) ); | ||
| // iterate through the nestedSettingPaths to find the blockName | ||
| for ( const nestedBlockName in nestedSettingPaths ) { |
There was a problem hiding this comment.
@alecgeatches - just need to pay special attention to this block as I touched it up a touch. I'd like to see if we could do some more pre-processing on the PHP side but that's for another PR.
There was a problem hiding this comment.
The main thing to keep in mind for this filter is that the blockEditor.useSetting.before filter runs a lot of times. In a quick test locally on a post with a moderately complex post, it's easy to hit this filter 10k+ times in a few seconds by just hovering around the page.
You may already have the fastest option here that's flexible, but if there's anything we can do to return early for non-matched blocks, we want to do so as quickly as possible.
There was a problem hiding this comment.
I've got one idea for optimization:
In JS prior to setting up this hook, we could split nestedSettingPaths into nestedSettingWildcards for names we need to evaluate like core/*, and a set of non-wildcards like nestedSettingNonWildcards (or a better name). Then we could keep the linear-time check that we had before using hasCustomSetting when matching non-wildcards, and only do a loop through any wildcards. If there are no wildcards, then there's no loop necessary.
There was a problem hiding this comment.
Overall I think this is pretty fast. I would split up wildcard and non-wildcard checks though.
There was a problem hiding this comment.
My thought was to try and do that on the PHP side so that we take advantage of server side rendering actually. That way we minimize the pre-processing necessary on the JS side 🤔
This is a good point, and something that I've now fixed. Lemme know if I missed any occurrence. |
|
I also added in support for 6.0 and PHP 8.0/8.3 in tests btw. |
Co-authored-by: Alec Geatches <alec.geatches@automattic.com>
…Automattic/vip-governance-plugin into add/support-for-regex-in-block-settings
|
@ingeniumed I'm seeing an issue with a custom palette under a {
"$schema": "https://api.wpvip.com/schemas/plugins/governance.json",
"version": "1.0.0",
"rules": [
{
"type": "role",
"roles": [ "administrator" ],
"allowedFeatures": [ "codeEditor", "lockBlocks" ],
"allowedBlocks": [ "core/media-text" ],
"blockSettings": {
"core/media-text": {
"core/*": {
"color": {
"text": true,
"palette": [
{
"color": "#ff00ff",
"name": "Custom purple",
"slug": "custom-purple"
}
]
}
}
}
}
},
{
"type": "default",
"allowedBlocks": [ "core/heading", "core/paragraph", "core/image" ]
}
]
}In the editor, this works correctly. I made a However, the custom color doesn't appear on the frontend: This is the frontend CSS getting injected into the page: .wp-block-media-text .wp-block {
--wp--preset--color--custom-purple: #ff00ff;
}
.wp-block-media-text .wp-block.has-custom-purple-color {
color: var(--wp--preset--color--custom-purple) !important;
}
.wp-block-media-text .wp-block.has-custom-purple-background-color {
background-color: var(--wp--preset--color--custom-purple) !important;
}
.wp-block-media-text .wp-block.has-custom-purple-border-color {
border-color: var(--wp--preset--color--custom-purple) !important;
}The <div class="wp-block-media-text is-stacked-on-mobile">
<figure class="wp-block-media-text__media">
<img <!--...--> class="wp-image-273 size-full">
</figure>
<div class="wp-block-media-text__content">
<h2
class="wp-block-heading has-custom-purple-color has-text-color has-link-color wp-elements-f7bf55209eb97c294140446761d1d65d"
>Heading</h2>
</div>
</div>Above, the This makes me wonder if we need to generate a matching rule for all possible subblocks, although would probably get exponential quickly with a handful of nested wildcards. Any idea on how to solve this? |
alecgeatches
left a comment
There was a problem hiding this comment.
Left some comments! The main issue I found is here: #85 (comment), where the .wp-block trick doesn't work for headings. I'm not sure if this is something that'll be easy to get around given .wp-block doesn't seem to be consistent.
Great job on this feature otherwise! There's a lot of complexity figured out in here.
|
|
||
| For an example of this feature, refer [here](#default-wildcard-rule-set). | ||
|
|
||
| Note: `allowedBlocks` are not respected under a wildcard block within `blockSettings`. This will only be respected under a targeted block such as `core/quote`. |
There was a problem hiding this comment.
I don't really follow this. Could you maybe add an example of a improper ruleset ❌, and then maybe an example of a working one ✅ to explain the issue?
There was a problem hiding this comment.
Good point, I'll do that for an improper one. I've already linked an existing example for a proper one
There was a problem hiding this comment.
I added another update to this documentation. It still wasn't clear enough to me for a couple of reasons:
- We have an example of a bad schema, but it wasn't obvious to me what a fix looked like. I added a second example to show how a customer might work around the issue and still make use of wildcards.
- I don't like having only an incorrect example under the "Wildcards" header. If I was trying to work quickly, I might search for "wildcard" on the README page and just copy the first example I found without realizing it was meant to be a counterexample. I made that more clear with ❌/ ✅ right above both examples.
I added these as headings at the fifth level (#####), which I've purposefully excluded from the table of contents. Typically TOC generators have a set level of headings (e.g. 1-4), and subheadings below that level are excluded. I think that makes sense for the TOC here in this README as well.
| "text": false | ||
| } | ||
| }, | ||
| "core/*": { |
There was a problem hiding this comment.
Good thinking adding this as an example! I think you can remove the prior core/paragraph example though, as this covers that case. For me in VSCode, the whole set of examples fills in when I tab-in a rule:
I think this is redundant to have two rules to set color.text to false, as technically the second rule would cover the case of the first. We could either have the core/paragraph example show something different, or just remove it here.
There was a problem hiding this comment.
Good point, I'll replace it with a gradient rule
|
|
||
| ( { value: result } = getNestedSetting( blockNamePath, path, nestedSettings ) ); | ||
| // iterate through the nestedSettingPaths to find the blockName | ||
| for ( const nestedBlockName in nestedSettingPaths ) { |
There was a problem hiding this comment.
The main thing to keep in mind for this filter is that the blockEditor.useSetting.before filter runs a lot of times. In a quick test locally on a post with a moderately complex post, it's easy to hit this filter 10k+ times in a few seconds by just hovering around the page.
You may already have the fastest option here that's flexible, but if there's anything we can do to return early for non-matched blocks, we want to do so as quickly as possible.
|
|
||
| ( { value: result } = getNestedSetting( blockNamePath, path, nestedSettings ) ); | ||
| // iterate through the nestedSettingPaths to find the blockName | ||
| for ( const nestedBlockName in nestedSettingPaths ) { |
There was a problem hiding this comment.
I've got one idea for optimization:
In JS prior to setting up this hook, we could split nestedSettingPaths into nestedSettingWildcards for names we need to evaluate like core/*, and a set of non-wildcards like nestedSettingNonWildcards (or a better name). Then we could keep the linear-time check that we had before using hasCustomSetting when matching non-wildcards, and only do a loop through any wildcards. If there are no wildcards, then there's no loop necessary.
|
|
||
| ( { value: result } = getNestedSetting( blockNamePath, path, nestedSettings ) ); | ||
| // iterate through the nestedSettingPaths to find the blockName | ||
| for ( const nestedBlockName in nestedSettingPaths ) { |
There was a problem hiding this comment.
Overall I think this is pretty fast. I would split up wildcard and non-wildcard checks though.
| const nestedSettingPaths = getNestedSettingPaths( nestedSettings ); | ||
|
|
||
| // pull out all the wildcard block names. | ||
| const nestedWildcardPaths = Object.keys( nestedSettingPaths ).reduce( ( acc, blockName ) => { |
There was a problem hiding this comment.
Optimized it based on your suggestion and it def feels a touch faster
There was a problem hiding this comment.
Thank you! This is what I was picturing. I pushed up a small update to split these in one pass imperatively, a tiny optimization since we're going for speed here:
vip-governance-plugin/src/index.js
Lines 79 to 90 in 9b80bba
…Automattic/vip-governance-plugin into add/support-for-regex-in-block-settings
|
@ingeniumed Made some minor changes, going to merge this! |



Description
There are 3 big changes in this PR:
allowedBlocks. This will solve Add support for wildcard block names when specifying block-specific settings rules #82. See this issue for an example in action.There's two small changes as well: