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
12 changes: 12 additions & 0 deletions includes/Modules/Features/Core_Block_Validation_Rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,18 @@ private function register_table_checks(): void {
'warning_msg' => __( 'Consider adding table headers.', 'accessibility-lab' ),
)
);
validation_api_register_block_check(
'core/table',
array(
'namespace' => self::NS,
'name' => 'check_table_caption',
'title' => __( 'Table caption recommended', 'accessibility-lab' ),
'level' => 'none',
'description' => __( 'Tables should have a caption to describe their purpose or content to screen reader users.', 'accessibility-lab' ),
'error_msg' => __( 'This table is missing a caption.', 'accessibility-lab' ),
'warning_msg' => __( 'Consider adding a caption to this table.', 'accessibility-lab' ),
)
);
}

/**
Expand Down
40 changes: 28 additions & 12 deletions src/editor/core-block-rules/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ type TableAttributes = {
caption?: string;
};

function stripHtml( html: string ): string {
return html
.replace( /<[^>]*>/g, '' )
.replace( /&nbsp;|\u00a0/g, ' ' )
.trim();
}

addFilter(
'editor.validateBlock',
'accessibility-lab-core-blocks/table',
Expand All @@ -25,19 +32,28 @@ addFilter(
return isValid;
}

if ( checkName !== 'check_table_headers' ) {
return isValid;
}
switch ( checkName ) {
case 'check_table_headers': {
const hasHead =
Array.isArray( attributes.head ) &&
attributes.head.length > 0;
if ( hasHead ) {
return true;
}
const firstRow = attributes.body?.[ 0 ];
if ( firstRow?.cells?.every( ( c ) => c.tag === 'th' ) ) {
return true;
}
return false;
}

const hasHead =
Array.isArray( attributes.head ) && attributes.head.length > 0;
if ( hasHead ) {
return true;
}
const firstRow = attributes.body?.[ 0 ];
if ( firstRow?.cells?.every( ( c ) => c.tag === 'th' ) ) {
return true;
case 'check_table_caption': {
const caption = stripHtml( String( attributes.caption ?? '' ) );
return caption.length > 0;
}

default:
return isValid;
}
return false;
}
);