Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Two words do a lot of work in this subsystem, so to be precise: **validation** n
Three of the first-party modules compose into a full block-editor validation subsystem:

1. **Block Validation Framework** — a plugin API (`validation_api_register_block_check()`, `validation_api_register_meta_check()`, `validation_api_register_editor_check()`), an `accessibility-lab/validation` data store, real-time debounced validation, publish locking, a Validation sidebar, and REST introspection at `GET /wp-validation/v1/checks`.
2. **Core block accessibility rules** — WCAG-oriented checks for `core/image`, `core/button`, `core/table`, `core/heading`, `core/gallery`, plus a required post/page title editor check.
2. **Core block accessibility rules** — WCAG-oriented checks for `core/image`, `core/video`, `core/button`, `core/table`, `core/heading`, `core/gallery`, plus a required post/page title editor check.
3. **Validation settings** — a single **Validation** admin page listing every registered check in a DataViews table, with search, sorting, pagination, and filters for check type, registering plugin, and severity. Admins set each check's severity to Error, Warning, or Disabled, and reset overridden checks back to their registered default. Third-party plugins that register checks appear in that table automatically, with zero admin-menu code.

Third parties integrate by calling the same `validation_api_register_*` functions and hooking the `editor.validateBlock` / `editor.validateMeta` / `editor.validateEditor` JS filters. **See [docs/features/validation-api.md](docs/features/validation-api.md)** for the full integration guide, including the filter signatures and worked PHP + JS examples for each scope.
Expand Down
2 changes: 1 addition & 1 deletion docs/features/validation-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ The plugin declares a starting severity; a site administrator can override it pe
The subsystem is three separately toggleable modules under **Settings → Accessibility Lab**:

1. **Block Validation Framework** — the registration API, the `accessibility-lab/validation` data store, the editor runtime, the Validation sidebar, publish locking, and REST introspection. Everything else depends on it.
2. **Core block accessibility rules** — WCAG checks for `core/image`, `core/button`, `core/table`, `core/heading` and `core/gallery`, plus required post and page titles. An optional consumer of the framework, and a working reference.
2. **Core block accessibility rules** — WCAG checks for `core/image`, `core/video`, `core/button`, `core/table`, `core/heading` and `core/gallery`, plus required post and page titles. An optional consumer of the framework, and a working reference.
3. **Validation settings** — the admin screen for adjusting severities.

Third-party checks need only the framework. If it's disabled, the `validation_api_register_*` functions don't exist, which is why every example below guards with `function_exists()`.
Expand Down
21 changes: 20 additions & 1 deletion includes/Modules/Features/Core_Block_Validation_Rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function name(): string {
* Returns the description for the core block accessibility rules module.
*/
public function description(): string {
return __( 'WCAG-oriented validation checks for the image, button, table, heading, and gallery core blocks, plus required post/page titles. Requires the Block Validation Framework module.', 'accessibility-lab' );
return __( 'WCAG-oriented validation checks for the image, video, button, table, heading, and gallery core blocks, plus required post/page titles. Requires the Block Validation Framework module.', 'accessibility-lab' );
}

/**
Expand Down Expand Up @@ -141,6 +141,7 @@ public function register_checks(): void {
);

$this->register_image_checks();
$this->register_video_checks();
$this->register_button_checks();
$this->register_table_checks();
$this->register_heading_checks();
Expand Down Expand Up @@ -253,6 +254,24 @@ private function register_button_checks(): void {
);
}

/**
* Registers video block accessibility checks.
*/
private function register_video_checks(): void {
validation_api_register_block_check(
'core/video',
array(
'namespace' => self::NS,
'name' => 'check_video_tracks',
'title' => __( 'Video captions or subtitles recommended', 'accessibility-lab' ),
'level' => 'warning',
'description' => __( 'Videos should provide captions or subtitles for deaf or hard-of-hearing users (WCAG 1.2.2).', 'accessibility-lab' ),
'error_msg' => __( 'This video is missing captions or subtitle tracks.', 'accessibility-lab' ),
'warning_msg' => __( 'Consider adding captions or subtitles to this video.', 'accessibility-lab' ),
)
);
}

/**
* Registers table block accessibility checks.
*/
Expand Down
2 changes: 1 addition & 1 deletion readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Included modules:

* Media Library: add view options — in-modal popover for infinite scroll, thumbnail density, always-show file names, and items-per-page. Per-user preferences.
* Block Validation Framework — third-party plugins can register real-time validation checks for blocks, post meta, and editor-level document concerns.
* Core block accessibility rules — WCAG-oriented validation for the image, button, table, heading, and gallery core blocks, plus required post/page titles.
* Core block accessibility rules — WCAG-oriented validation for the image, video, button, table, heading, and gallery core blocks, plus required post/page titles.
* Validation settings — a Validation admin page listing every registered validation check in a filterable, searchable table, where each check's severity can be set to Error, Warning, or Disabled.

== Installation ==
Expand Down
1 change: 1 addition & 0 deletions src/editor/core-block-rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ import './button';
import './table';
import './heading';
import './gallery';
import './video';
import './post-title';
72 changes: 72 additions & 0 deletions src/editor/core-block-rules/video.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* core/video validation logic.
*/

import { addFilter } from '@wordpress/hooks';

type Track = {
src?: string;
kind?: string;
label?: string;
srcLang?: string;
};

type VideoAttributes = {
id?: number;
src?: string;
autoplay?: boolean;
controls?: boolean;
loop?: boolean;
muted?: boolean;
tracks?: Track[];
};

addFilter(
'editor.validateBlock',
'accessibility-lab-core-blocks/video',
(
isValid: boolean,
blockType: string,
attributes: VideoAttributes,
checkName: string
) => {
if ( blockType !== 'core/video' ) {
return isValid;
}

const hasVideo = Boolean( attributes.src || attributes.id );

switch ( checkName ) {
case 'check_video_tracks': {
// If no video file is attached yet, do not trigger unconfigured warning.
if ( ! hasVideo ) {
return true;
}
// Muted, looping, autoplaying video without controls is a
// background/decorative clip with no audio to caption.
const isBackground =
attributes.autoplay &&
attributes.muted &&
attributes.loop &&
attributes.controls === false;
if ( isBackground ) {
return true;
}
const tracks = Array.isArray( attributes.tracks )
? attributes.tracks
: [];
return tracks.some(
( track ) =>
Boolean( track?.src ) &&
// A <track> without `kind` defaults to subtitles.
[ 'captions', 'subtitles', undefined ].includes(
track?.kind
)
);
}

default:
return isValid;
}
}
);