@automattic/newspack-blocks 4.29.2 → 4.30.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/editor.asset.php +1 -1
- package/dist/editor.js +6 -6
- package/includes/class-newspack-blocks-caching.php +2 -2
- package/includes/class-newspack-blocks.php +148 -35
- package/newspack-blocks.php +2 -2
- package/package.json +5 -5
- package/src/blocks/author-list/view.php +2 -2
- package/src/blocks/author-profile/view.php +1 -1
- package/src/blocks/carousel/view.php +1 -1
- package/src/blocks/checkout-button/view.php +1 -1
- package/src/blocks/donate/utils.test.js +37 -0
- package/src/blocks/donate/utils.ts +65 -16
- package/src/blocks/homepage-articles/view.php +1 -1
- package/src/blocks/iframe/view.php +1 -1
- package/vendor/composer/installed.php +2 -2
|
@@ -253,9 +253,9 @@ class Newspack_Blocks_Caching {
|
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
if ( 'newspack-blocks/homepage-articles' === $block_data['blockName'] ) {
|
|
256
|
-
Newspack_Blocks::enqueue_view_assets( 'homepage-articles' );
|
|
256
|
+
Newspack_Blocks::enqueue_view_assets( 'homepage-articles', 'defer' );
|
|
257
257
|
} elseif ( 'newspack-blocks/carousel' === $block_data['blockName'] ) {
|
|
258
|
-
Newspack_Blocks::enqueue_view_assets( 'carousel' );
|
|
258
|
+
Newspack_Blocks::enqueue_view_assets( 'carousel', 'defer' );
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
return $cached_data['cached_content'];
|
|
@@ -25,6 +25,7 @@ class Newspack_Blocks {
|
|
|
25
25
|
*/
|
|
26
26
|
public static function init() {
|
|
27
27
|
add_action( 'after_setup_theme', [ __CLASS__, 'add_image_sizes' ] );
|
|
28
|
+
add_filter( 'intermediate_image_sizes_advanced', [ __CLASS__, 'maybe_skip_article_block_image_subsizes' ] );
|
|
28
29
|
add_post_type_support( 'post', 'newspack_blocks' );
|
|
29
30
|
add_post_type_support( 'page', 'newspack_blocks' );
|
|
30
31
|
add_action( 'jetpack_register_gutenberg_extensions', [ __CLASS__, 'disable_jetpack_donate' ], 99 );
|
|
@@ -340,9 +341,13 @@ class Newspack_Blocks {
|
|
|
340
341
|
/**
|
|
341
342
|
* Enqueue view scripts and styles for a single block.
|
|
342
343
|
*
|
|
343
|
-
* @param string
|
|
344
|
+
* @param string $type The block's type.
|
|
345
|
+
* @param string|null $strategy Optional. Script loading strategy to apply to the
|
|
346
|
+
* view script ('defer' or 'async'). First write wins:
|
|
347
|
+
* ignored if a strategy is already set on the handle.
|
|
348
|
+
* Default null (no strategy).
|
|
344
349
|
*/
|
|
345
|
-
public static function enqueue_view_assets( $type ) {
|
|
350
|
+
public static function enqueue_view_assets( $type, $strategy = null ) {
|
|
346
351
|
$style_path = apply_filters(
|
|
347
352
|
'newspack_blocks_enqueue_view_assets',
|
|
348
353
|
NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . $type . '/view.css',
|
|
@@ -362,13 +367,17 @@ class Newspack_Blocks {
|
|
|
362
367
|
}
|
|
363
368
|
$script_data = static::script_enqueue_helper( NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . $type . '/view.js' );
|
|
364
369
|
if ( $script_data ) {
|
|
370
|
+
$handle = "newspack-blocks-{$type}";
|
|
365
371
|
wp_enqueue_script(
|
|
366
|
-
|
|
372
|
+
$handle,
|
|
367
373
|
$script_data['script_path'],
|
|
368
374
|
$script_data['dependencies'],
|
|
369
375
|
$script_data['version'],
|
|
370
376
|
true
|
|
371
377
|
);
|
|
378
|
+
if ( $strategy && ! wp_scripts()->get_data( $handle, 'strategy' ) ) {
|
|
379
|
+
wp_script_add_data( $handle, 'strategy', $strategy );
|
|
380
|
+
}
|
|
372
381
|
}
|
|
373
382
|
}
|
|
374
383
|
|
|
@@ -543,6 +552,70 @@ class Newspack_Blocks {
|
|
|
543
552
|
add_image_size( 'newspack-article-block-uncropped', 1200, 9999, false );
|
|
544
553
|
}
|
|
545
554
|
|
|
555
|
+
/**
|
|
556
|
+
* Skip generating the physical `newspack-article-block-*` sub-size files on upload.
|
|
557
|
+
*
|
|
558
|
+
* The sizes stay registered, so blocks still resolve correctly-cropped URLs;
|
|
559
|
+
* we only skip writing the files where an on-the-fly image CDN can reproduce them
|
|
560
|
+
* from the registered sizes. The prefix match removes every `newspack-article-block-*`
|
|
561
|
+
* sub-size, including `newspack-article-block-uncropped` (registered with
|
|
562
|
+
* `crop => false` — a plain downscale, not a crop); the CDN resizes as well as
|
|
563
|
+
* crops, so none of them need a physical file. This also makes the Image block
|
|
564
|
+
* (REST) and Media Library upload paths behave the same on wpcom, where they
|
|
565
|
+
* otherwise differ.
|
|
566
|
+
*
|
|
567
|
+
* @param array $sizes Image sub-sizes to generate, keyed by size name.
|
|
568
|
+
* @return array Filtered sizes.
|
|
569
|
+
*/
|
|
570
|
+
public static function maybe_skip_article_block_image_subsizes( array $sizes ): array {
|
|
571
|
+
/**
|
|
572
|
+
* Filters whether to skip physical `newspack-article-block-*` sub-size generation.
|
|
573
|
+
* Defaults to true where an on-the-fly image CDN reproduces the sizes: WordPress.com
|
|
574
|
+
* Simple (always) and Atomic (only when the Jetpack Image CDN is active). Self-hosted
|
|
575
|
+
* sites can opt in, e.g. when fronting uploads with the Jetpack Image CDN.
|
|
576
|
+
*
|
|
577
|
+
* @param bool $skip Whether to skip physical sub-size generation.
|
|
578
|
+
*/
|
|
579
|
+
$skip = apply_filters( 'newspack_blocks_skip_article_image_subsizes', self::is_wpcom_image_cdn_active() );
|
|
580
|
+
if ( ! $skip ) {
|
|
581
|
+
return $sizes;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
foreach ( array_keys( $sizes ) as $size_name ) {
|
|
585
|
+
if ( is_string( $size_name ) && str_starts_with( $size_name, 'newspack-article-block-' ) ) {
|
|
586
|
+
unset( $sizes[ $size_name ] );
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return $sizes;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Whether this site serves images through an on-the-fly image CDN that crops and
|
|
594
|
+
* resizes from the registered sizes, making the physical `newspack-article-block-*`
|
|
595
|
+
* files redundant.
|
|
596
|
+
*
|
|
597
|
+
* WordPress.com Simple always serves images through the platform image CDN. On
|
|
598
|
+
* Atomic the Jetpack Image CDN (Photon) can be toggled off, so it counts only when
|
|
599
|
+
* the module is active — otherwise the crops must still be generated. Self-hosted
|
|
600
|
+
* sites are not auto-detected here; they opt in via the filter above.
|
|
601
|
+
*
|
|
602
|
+
* @return bool
|
|
603
|
+
*/
|
|
604
|
+
private static function is_wpcom_image_cdn_active(): bool {
|
|
605
|
+
if ( ! class_exists( '\Automattic\Jetpack\Status\Host' ) ) {
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
$host = new \Automattic\Jetpack\Status\Host();
|
|
609
|
+
if ( $host->is_wpcom_simple() ) {
|
|
610
|
+
return true;
|
|
611
|
+
}
|
|
612
|
+
if ( $host->is_wpcom_platform() ) {
|
|
613
|
+
// Atomic: only skip when the Image CDN (Photon) is actually active to crop on the fly.
|
|
614
|
+
return class_exists( 'Jetpack' ) && \Jetpack::is_module_active( 'photon' );
|
|
615
|
+
}
|
|
616
|
+
return false;
|
|
617
|
+
}
|
|
618
|
+
|
|
546
619
|
/**
|
|
547
620
|
* Whether the block should be included in the deduplication logic.
|
|
548
621
|
*
|
|
@@ -1387,44 +1460,84 @@ class Newspack_Blocks {
|
|
|
1387
1460
|
}
|
|
1388
1461
|
|
|
1389
1462
|
/**
|
|
1390
|
-
* Pick either
|
|
1391
|
-
* From Newspack Theme functions.
|
|
1463
|
+
* Pick either black or white text, whichever reads better on the given background.
|
|
1392
1464
|
*
|
|
1393
|
-
*
|
|
1394
|
-
*
|
|
1465
|
+
* Scores pure black and pure white as text against the background and returns
|
|
1466
|
+
* whichever produces the greater APCA lightness contrast (Lc); ties fall to
|
|
1467
|
+
* black. The constants are the SA98G set from apca-w3 0.1.9.
|
|
1395
1468
|
*
|
|
1396
|
-
*
|
|
1469
|
+
* Keep in sync with getColorForContrast() in src/blocks/donate/utils.ts.
|
|
1470
|
+
*
|
|
1471
|
+
* @param string $hex Hexadecimal background color (#RGB, #RRGGBB or #RRGGBBAA, with or without #).
|
|
1472
|
+
* @return string Either 'black' or 'white' (literal CSS color keywords).
|
|
1397
1473
|
*/
|
|
1398
1474
|
public static function get_color_for_contrast( $hex ) {
|
|
1399
|
-
|
|
1400
|
-
$
|
|
1401
|
-
$
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
$
|
|
1475
|
+
$background_y = self::get_apca_luminance( $hex );
|
|
1476
|
+
$black_lc = self::get_apca_contrast( $background_y, self::get_apca_luminance( '#000000' ) );
|
|
1477
|
+
$white_lc = self::get_apca_contrast( $background_y, self::get_apca_luminance( '#ffffff' ) );
|
|
1478
|
+
|
|
1479
|
+
return abs( $white_lc ) > abs( $black_lc ) ? 'white' : 'black';
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
/**
|
|
1483
|
+
* Compute the soft-clamped APCA screen luminance (Y) of a hex color.
|
|
1484
|
+
*
|
|
1485
|
+
* Accepts #RGB, #RRGGBB and #RRGGBBAA (the alpha pair is stripped), with or
|
|
1486
|
+
* without the leading #, case-insensitively. Unparseable input is treated as
|
|
1487
|
+
* white (luminance 1.0) so callers fall back to black text.
|
|
1488
|
+
*
|
|
1489
|
+
* @param string $hex Hexadecimal color.
|
|
1490
|
+
* @return float Soft-clamped luminance in the 0..1 range.
|
|
1491
|
+
*/
|
|
1492
|
+
private static function get_apca_luminance( $hex ) {
|
|
1493
|
+
$hex = ltrim( trim( (string) $hex ), '#' );
|
|
1494
|
+
if ( 3 === strlen( $hex ) ) {
|
|
1495
|
+
$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
|
|
1496
|
+
} elseif ( 8 === strlen( $hex ) ) {
|
|
1497
|
+
// Drop the alpha pair from #RRGGBBAA.
|
|
1498
|
+
$hex = substr( $hex, 0, 6 );
|
|
1420
1499
|
}
|
|
1421
|
-
if ( $
|
|
1422
|
-
|
|
1423
|
-
return 'black';
|
|
1424
|
-
} else {
|
|
1425
|
-
// if not, return white color.
|
|
1426
|
-
return 'white';
|
|
1500
|
+
if ( 6 !== strlen( $hex ) || ! ctype_xdigit( $hex ) ) {
|
|
1501
|
+
return 1.0;
|
|
1427
1502
|
}
|
|
1503
|
+
|
|
1504
|
+
$r = hexdec( substr( $hex, 0, 2 ) ) / 255;
|
|
1505
|
+
$g = hexdec( substr( $hex, 2, 2 ) ) / 255;
|
|
1506
|
+
$b = hexdec( substr( $hex, 4, 2 ) ) / 255;
|
|
1507
|
+
|
|
1508
|
+
$y = 0.2126729 * pow( $r, 2.4 ) + 0.7151522 * pow( $g, 2.4 ) + 0.0721750 * pow( $b, 2.4 );
|
|
1509
|
+
|
|
1510
|
+
// APCA soft-clamp of near-black luminance.
|
|
1511
|
+
if ( $y <= 0.022 ) {
|
|
1512
|
+
$y += pow( 0.022 - $y, 1.414 );
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
return $y;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
/**
|
|
1519
|
+
* Compute the APCA lightness contrast (Lc) of text on a background.
|
|
1520
|
+
*
|
|
1521
|
+
* Positive values are dark text on a lighter background; negative values are
|
|
1522
|
+
* light text on a darker background. Both luminances must already be
|
|
1523
|
+
* soft-clamped.
|
|
1524
|
+
*
|
|
1525
|
+
* @param float $background_y Soft-clamped background luminance.
|
|
1526
|
+
* @param float $text_y Soft-clamped text luminance.
|
|
1527
|
+
* @return float The Lc value.
|
|
1528
|
+
*/
|
|
1529
|
+
private static function get_apca_contrast( $background_y, $text_y ) {
|
|
1530
|
+
if ( abs( $background_y - $text_y ) < 0.0005 ) {
|
|
1531
|
+
return 0.0;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
if ( $background_y > $text_y ) {
|
|
1535
|
+
$sapc = ( pow( $background_y, 0.56 ) - pow( $text_y, 0.57 ) ) * 1.14;
|
|
1536
|
+
return $sapc < 0.1 ? 0.0 : ( $sapc - 0.027 ) * 100;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
$sapc = ( pow( $background_y, 0.65 ) - pow( $text_y, 0.62 ) ) * 1.14;
|
|
1540
|
+
return $sapc > -0.1 ? 0.0 : ( $sapc + 0.027 ) * 100;
|
|
1428
1541
|
}
|
|
1429
1542
|
|
|
1430
1543
|
/**
|
package/newspack-blocks.php
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Author URI: https://newspack.com/
|
|
8
8
|
* Text Domain: newspack-blocks
|
|
9
9
|
* Domain Path: /languages
|
|
10
|
-
* Version: 4.
|
|
10
|
+
* Version: 4.30.0-alpha.2
|
|
11
11
|
*
|
|
12
12
|
* @package Newspack_Blocks
|
|
13
13
|
*/
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
define( 'NEWSPACK_BLOCKS__PLUGIN_FILE', __FILE__ );
|
|
16
16
|
define( 'NEWSPACK_BLOCKS__BLOCKS_DIRECTORY', 'dist/' );
|
|
17
17
|
define( 'NEWSPACK_BLOCKS__PLUGIN_DIR', plugin_dir_path( NEWSPACK_BLOCKS__PLUGIN_FILE ) );
|
|
18
|
-
define( 'NEWSPACK_BLOCKS__VERSION', '4.
|
|
18
|
+
define( 'NEWSPACK_BLOCKS__VERSION', '4.30.0-alpha.2' );
|
|
19
19
|
|
|
20
20
|
require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks.php';
|
|
21
21
|
require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks-api.php';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/newspack-blocks",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.30.0-alpha.2",
|
|
4
4
|
"author": "Automattic",
|
|
5
5
|
"description": "=== Newspack Blocks === Contributors: (this should be a list of wordpress.org userid's) Donate link: https://example.com/ Tags: comments, spam Requires at least: 4.5 Tested up to: 5.1.1 Stable tag: 0.1.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html",
|
|
6
6
|
"repository": {
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"classnames": "^2.5.1",
|
|
48
48
|
"lodash": "^4.17.21",
|
|
49
|
-
"newspack-colors": "1.1.1",
|
|
50
|
-
"newspack-icons": "1.1.
|
|
49
|
+
"newspack-colors": "1.1.2-alpha.1",
|
|
50
|
+
"newspack-icons": "1.1.1-alpha.1",
|
|
51
51
|
"redux": "^5.0.0",
|
|
52
52
|
"redux-saga": "^1.5.0",
|
|
53
53
|
"regenerator-runtime": "^0.14.1",
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/lodash": "^4.17.23",
|
|
58
|
-
"newspack-components": "4.6.
|
|
59
|
-
"newspack-scripts": "5.
|
|
58
|
+
"newspack-components": "4.6.1-alpha.1",
|
|
59
|
+
"newspack-scripts": "5.11.0-alpha.1"
|
|
60
60
|
},
|
|
61
61
|
"overrides": {
|
|
62
62
|
"path-to-regexp": "1.7.0"
|
|
@@ -78,8 +78,8 @@ function newspack_blocks_render_block_author_list( $attributes ) {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// Enqueue required front-end assets.
|
|
81
|
-
Newspack_Blocks::enqueue_view_assets( 'author-list' );
|
|
82
|
-
Newspack_Blocks::enqueue_view_assets( 'author-profile' );
|
|
81
|
+
Newspack_Blocks::enqueue_view_assets( 'author-list', 'defer' );
|
|
82
|
+
Newspack_Blocks::enqueue_view_assets( 'author-profile', 'defer' );
|
|
83
83
|
|
|
84
84
|
// Class names for the list container.
|
|
85
85
|
$container_classes = [ 'newspack-blocks__author-list-container' ];
|
|
@@ -320,7 +320,7 @@ function newspack_blocks_render_block_author_profile( $attributes, $content, $bl
|
|
|
320
320
|
return '';
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
-
Newspack_Blocks::enqueue_view_assets( 'author-profile' );
|
|
323
|
+
Newspack_Blocks::enqueue_view_assets( 'author-profile', 'defer' );
|
|
324
324
|
|
|
325
325
|
// NESTED MODE: Determined by layoutVersion attribute, not theme type.
|
|
326
326
|
// Once a block is created in nested mode (layoutVersion 2), it stays nested.
|
|
@@ -269,7 +269,7 @@ function newspack_blocks_render_block_carousel( $attributes ) {
|
|
|
269
269
|
$data_attributes[] = 'data-autoplay=1';
|
|
270
270
|
$data_attributes[] = sprintf( 'data-autoplay_delay=%s', esc_attr( $delay ) );
|
|
271
271
|
}
|
|
272
|
-
Newspack_Blocks::enqueue_view_assets( 'carousel' );
|
|
272
|
+
Newspack_Blocks::enqueue_view_assets( 'carousel', 'defer' );
|
|
273
273
|
if ( 1 === $counter ) {
|
|
274
274
|
$selector = '';
|
|
275
275
|
}
|
|
@@ -81,7 +81,7 @@ function render_callback( $attributes ) {
|
|
|
81
81
|
? $attributes['product']
|
|
82
82
|
: $product_id;
|
|
83
83
|
\Newspack_Blocks\Modal_Checkout::enqueue_modal( $modal_product_id );
|
|
84
|
-
\Newspack_Blocks::enqueue_view_assets( 'checkout-button' );
|
|
84
|
+
\Newspack_Blocks::enqueue_view_assets( 'checkout-button', 'defer' );
|
|
85
85
|
|
|
86
86
|
$background_color = $attributes['backgroundColor'] ?? '';
|
|
87
87
|
$text_color = $attributes['textColor'] ?? '';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getColorForContrast } from './utils';
|
|
2
|
+
|
|
3
|
+
describe( 'getColorForContrast', () => {
|
|
4
|
+
// Must stay in parity with Newspack_Blocks::get_color_for_contrast(), which
|
|
5
|
+
// runs the same APCA math (see tests/test-color-contrast.php).
|
|
6
|
+
it.each( [
|
|
7
|
+
[ '#000000', '#ffffff' ],
|
|
8
|
+
[ '#ffffff', '#000000' ],
|
|
9
|
+
[ '#f0f0f0', '#000000' ],
|
|
10
|
+
[ '#ffcc00', '#000000' ],
|
|
11
|
+
// APCA flip zone: WCAG2 said black, APCA says white decisively.
|
|
12
|
+
[ '#178f15', '#ffffff' ],
|
|
13
|
+
[ '#3366cc', '#ffffff' ],
|
|
14
|
+
[ '#dd3333', '#ffffff' ],
|
|
15
|
+
[ '#fff', '#000000' ],
|
|
16
|
+
[ '#36c', '#ffffff' ],
|
|
17
|
+
[ 'not-a-color', '#000000' ],
|
|
18
|
+
// Parity cases shared with the PHP fixture table.
|
|
19
|
+
[ '3366cc', '#ffffff' ],
|
|
20
|
+
[ '178f15', '#ffffff' ],
|
|
21
|
+
[ '', '#000000' ],
|
|
22
|
+
[ '#33333380', '#ffffff' ],
|
|
23
|
+
[ '#FFCC00', '#000000' ],
|
|
24
|
+
[ ' #178f15 ', '#ffffff' ],
|
|
25
|
+
] )( 'picks readable text for %s', ( background, expected ) => {
|
|
26
|
+
expect( getColorForContrast( background ) ).toBe( expected );
|
|
27
|
+
} );
|
|
28
|
+
|
|
29
|
+
it( 'falls back to black when no color is provided', () => {
|
|
30
|
+
expect( getColorForContrast( undefined ) ).toBe( '#000000' );
|
|
31
|
+
} );
|
|
32
|
+
|
|
33
|
+
it( 'expands 3-digit hex the same as 6-digit hex', () => {
|
|
34
|
+
expect( getColorForContrast( '#36c' ) ).toBe( getColorForContrast( '#3366cc' ) );
|
|
35
|
+
expect( getColorForContrast( '#fff' ) ).toBe( getColorForContrast( '#ffffff' ) );
|
|
36
|
+
} );
|
|
37
|
+
} );
|
|
@@ -1,17 +1,74 @@
|
|
|
1
1
|
import { __, _x, sprintf } from '@wordpress/i18n';
|
|
2
2
|
import type { DonationFrequencySlug } from './types';
|
|
3
3
|
|
|
4
|
+
// Normalize a hex color to exactly six lowercase hex digits (no leading #).
|
|
5
|
+
// Accepts #RGB, #RRGGBB and #RRGGBBAA (the alpha pair is stripped), with or
|
|
6
|
+
// without the leading #, case-insensitively; returns null when unparseable.
|
|
7
|
+
// Keep in sync with Newspack_Blocks::get_apca_luminance() in
|
|
8
|
+
// includes/class-newspack-blocks.php.
|
|
9
|
+
const normalizeHex = ( color: string ): string | null => {
|
|
10
|
+
let hex = color.trim().replace( /^#/, '' ).toLowerCase();
|
|
11
|
+
if ( hex.length === 3 ) {
|
|
12
|
+
hex = hex[ 0 ] + hex[ 0 ] + hex[ 1 ] + hex[ 1 ] + hex[ 2 ] + hex[ 2 ];
|
|
13
|
+
} else if ( hex.length === 8 ) {
|
|
14
|
+
hex = hex.substring( 0, 6 );
|
|
15
|
+
}
|
|
16
|
+
return /^[a-f\d]{6}$/.test( hex ) ? hex : null;
|
|
17
|
+
};
|
|
18
|
+
|
|
4
19
|
const hexToRGB = ( hex: string ): number[] => {
|
|
5
|
-
const parts = hex
|
|
6
|
-
.replace( /^#?([a-f\d])([a-f\d])([a-f\d])$/i, ( m, r, g, b ) => '#' + r + r + g + g + b + b )
|
|
7
|
-
.substring( 1 )
|
|
8
|
-
.match( /.{2}/g );
|
|
20
|
+
const parts = hex.match( /.{2}/g );
|
|
9
21
|
if ( parts === null ) {
|
|
10
22
|
return [ 0, 0, 0 ];
|
|
11
23
|
}
|
|
12
24
|
return parts.map( x => parseInt( x, 16 ) );
|
|
13
25
|
};
|
|
14
26
|
|
|
27
|
+
// APCA soft-clamps near-black luminance and treats unparseable input as white
|
|
28
|
+
// (luminance 1) so callers fall back to black text.
|
|
29
|
+
const apcaLuminance = ( color: string ): number => {
|
|
30
|
+
const hex = normalizeHex( color );
|
|
31
|
+
if ( hex === null ) {
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const [ r, g, b ] = hexToRGB( hex );
|
|
36
|
+
|
|
37
|
+
let y = 0.2126729 * Math.pow( r / 255, 2.4 ) + 0.7151522 * Math.pow( g / 255, 2.4 ) + 0.072175 * Math.pow( b / 255, 2.4 );
|
|
38
|
+
|
|
39
|
+
if ( y <= 0.022 ) {
|
|
40
|
+
y += Math.pow( 0.022 - y, 1.414 );
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return y;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// APCA lightness contrast (Lc): positive is dark text on a lighter background,
|
|
47
|
+
// negative is light text on a darker background. Both luminances are clamped.
|
|
48
|
+
const apcaContrast = ( backgroundY: number, textY: number ): number => {
|
|
49
|
+
if ( Math.abs( backgroundY - textY ) < 0.0005 ) {
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if ( backgroundY > textY ) {
|
|
54
|
+
const sapc = ( Math.pow( backgroundY, 0.56 ) - Math.pow( textY, 0.57 ) ) * 1.14;
|
|
55
|
+
return sapc < 0.1 ? 0 : ( sapc - 0.027 ) * 100;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const sapc = ( Math.pow( backgroundY, 0.65 ) - Math.pow( textY, 0.62 ) ) * 1.14;
|
|
59
|
+
return sapc > -0.1 ? 0 : ( sapc + 0.027 ) * 100;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Pick either black or white text, whichever reads better on the given background.
|
|
64
|
+
*
|
|
65
|
+
* Scores pure black and pure white as text against the background and returns
|
|
66
|
+
* whichever produces the greater APCA lightness contrast (Lc); ties fall to
|
|
67
|
+
* black. The constants are the SA98G set from apca-w3 0.1.9.
|
|
68
|
+
*
|
|
69
|
+
* Keep in sync with Newspack_Blocks::get_color_for_contrast() in
|
|
70
|
+
* includes/class-newspack-blocks.php.
|
|
71
|
+
*/
|
|
15
72
|
export const getColorForContrast = ( color?: string ): string => {
|
|
16
73
|
const blackColor = '#000000';
|
|
17
74
|
const whiteColor = '#ffffff';
|
|
@@ -19,19 +76,11 @@ export const getColorForContrast = ( color?: string ): string => {
|
|
|
19
76
|
return blackColor;
|
|
20
77
|
}
|
|
21
78
|
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
const l1 =
|
|
26
|
-
0.2126 * Math.pow( backgroundColorRGB[ 0 ] / 255, 2.2 ) +
|
|
27
|
-
0.7152 * Math.pow( backgroundColorRGB[ 1 ] / 255, 2.2 ) +
|
|
28
|
-
0.0722 * Math.pow( backgroundColorRGB[ 2 ] / 255, 2.2 );
|
|
29
|
-
const l2 =
|
|
30
|
-
0.2126 * Math.pow( blackRGB[ 0 ] / 255, 2.2 ) + 0.7152 * Math.pow( blackRGB[ 1 ] / 255, 2.2 ) + 0.0722 * Math.pow( blackRGB[ 2 ] / 255, 2.2 );
|
|
31
|
-
|
|
32
|
-
const contrastRatio = l1 > l2 ? ( l1 + 0.05 ) / ( l2 + 0.05 ) : ( l2 + 0.05 ) / ( l1 + 0.05 );
|
|
79
|
+
const backgroundY = apcaLuminance( color );
|
|
80
|
+
const blackLc = apcaContrast( backgroundY, apcaLuminance( blackColor ) );
|
|
81
|
+
const whiteLc = apcaContrast( backgroundY, apcaLuminance( whiteColor ) );
|
|
33
82
|
|
|
34
|
-
return
|
|
83
|
+
return Math.abs( whiteLc ) > Math.abs( blackLc ) ? whiteColor : blackColor;
|
|
35
84
|
};
|
|
36
85
|
|
|
37
86
|
export const getMigratedAmount = (
|
|
@@ -422,7 +422,7 @@ function newspack_blocks_render_block_homepage_articles( $attributes ) {
|
|
|
422
422
|
<?php
|
|
423
423
|
|
|
424
424
|
$content = ob_get_clean();
|
|
425
|
-
Newspack_Blocks::enqueue_view_assets( 'homepage-articles' );
|
|
425
|
+
Newspack_Blocks::enqueue_view_assets( 'homepage-articles', 'defer' );
|
|
426
426
|
|
|
427
427
|
return $content;
|
|
428
428
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @return string
|
|
14
14
|
*/
|
|
15
15
|
function newspack_blocks_render_block_iframe( $attributes ) {
|
|
16
|
-
Newspack_Blocks::enqueue_view_assets( 'iframe' );
|
|
16
|
+
Newspack_Blocks::enqueue_view_assets( 'iframe', 'defer' );
|
|
17
17
|
|
|
18
18
|
return newspack_blocks_get_iframe( $attributes );
|
|
19
19
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
'name' => 'automattic/newspack-blocks',
|
|
4
4
|
'pretty_version' => 'dev-main',
|
|
5
5
|
'version' => 'dev-main',
|
|
6
|
-
'reference' => '
|
|
6
|
+
'reference' => '676b21e16de65c4c31fba7e48dcf23dd93dfcd1c',
|
|
7
7
|
'type' => 'wordpress-plugin',
|
|
8
8
|
'install_path' => __DIR__ . '/../../',
|
|
9
9
|
'aliases' => array(),
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
'automattic/newspack-blocks' => array(
|
|
14
14
|
'pretty_version' => 'dev-main',
|
|
15
15
|
'version' => 'dev-main',
|
|
16
|
-
'reference' => '
|
|
16
|
+
'reference' => '676b21e16de65c4c31fba7e48dcf23dd93dfcd1c',
|
|
17
17
|
'type' => 'wordpress-plugin',
|
|
18
18
|
'install_path' => __DIR__ . '/../../',
|
|
19
19
|
'aliases' => array(),
|