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
1 change: 1 addition & 0 deletions includes/class-create-block-theme-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
require_once __DIR__ . '/create-theme/theme-readme.php';
require_once __DIR__ . '/create-theme/theme-fonts.php';
require_once __DIR__ . '/create-theme/theme-create.php';
require_once __DIR__ . '/create-theme/theme-fluid-typography.php';

/**
* The api functionality of the plugin leveraged by the site editor UI.
Expand Down
68 changes: 68 additions & 0 deletions includes/create-theme/theme-fluid-typography.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

class CBT_Theme_Fluid_Typography {

/**
* Sync the size property with fluid.max in font sizes.
* This ensures that when fluid typography is edited, the size property
* stays in sync with the maximum fluid size.
*
* @param array $data The theme.json data to process.
* @return array The processed data with synced sizes.
*/
public static function sync_fluid_typography_sizes( $data ) {
if ( ! isset( $data['settings']['typography']['fontSizes'] ) ) {
return $data;
}

$font_sizes = $data['settings']['typography']['fontSizes'];

foreach ( $font_sizes as $key => $font_size ) {
// Check if this font size has fluid settings
if ( isset( $font_size['fluid'] ) && is_array( $font_size['fluid'] ) ) {
// If fluid.max is set, sync it with size
if ( isset( $font_size['fluid']['max'] ) ) {
$font_sizes[ $key ]['size'] = $font_size['fluid']['max'];
}
}
}

$data['settings']['typography']['fontSizes'] = $font_sizes;

return $data;
}

/**
* Hook into the global styles REST API to sync fluid typography sizes.
*/
public static function init() {
add_filter( 'rest_pre_insert_wp_global_styles', array( __CLASS__, 'sync_global_styles_fluid_typography' ), 10, 2 );
}

/**
* Sync fluid typography in global styles before saving.
*
* @param stdClass $prepared_post The prepared post object.
* @return stdClass The modified prepared post object.
*/
public static function sync_global_styles_fluid_typography( $prepared_post ) {
if ( ! isset( $prepared_post->post_content ) ) {
return $prepared_post;
}

$data = json_decode( $prepared_post->post_content, true );

if ( ! is_array( $data ) ) {
return $prepared_post;
}

$data = self::sync_fluid_typography_sizes( $data );

$prepared_post->post_content = wp_json_encode( $data );

return $prepared_post;
}
}

// Initialize the fluid typography sync on plugins_loaded
add_action( 'plugins_loaded', array( 'CBT_Theme_Fluid_Typography', 'init' ) );
129 changes: 129 additions & 0 deletions tests/test-fluid-typography.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php
/**
* @package Create_Block_Theme
* @group fluid-typography
*/
class Test_Create_Block_Theme_Fluid_Typography extends WP_UnitTestCase {

/**
* Test that fluid typography sizes are synced correctly
*/
public function test_sync_fluid_typography_sizes() {
$data = array(
'settings' => array(
'typography' => array(
'fontSizes' => array(
array(
'slug' => 'custom-fluid',
'name' => 'Custom Fluid',
'fluid' => array(
'min' => '1.5rem',
'max' => '5.63rem',
),
'size' => '3rem', // Old value, should be updated
),
array(
'slug' => 'normal',
'name' => 'Normal',
'size' => '1rem', // No fluid, should remain unchanged
),
),
),
),
);

$result = CBT_Theme_Fluid_Typography::sync_fluid_typography_sizes( $data );

// Verify the fluid size was synced
$this->assertEquals(
'5.63rem',
$result['settings']['typography']['fontSizes'][0]['size'],
'Fluid typography size should be synced with fluid.max'
);

// Verify the non-fluid size remained unchanged
$this->assertEquals(
'1rem',
$result['settings']['typography']['fontSizes'][1]['size'],
'Non-fluid typography size should remain unchanged'
);
}

/**
* Test that global styles filter works correctly
*/
public function test_sync_global_styles_fluid_typography() {
$prepared_post = new stdClass();
$prepared_post->post_content = wp_json_encode(
array(
'settings' => array(
'typography' => array(
'fontSizes' => array(
array(
'slug' => 'custom-fluid',
'name' => 'Custom Fluid',
'fluid' => array(
'min' => '1.5rem',
'max' => '5.63rem',
),
'size' => '3rem',
),
),
),
),
)
);

$result = CBT_Theme_Fluid_Typography::sync_global_styles_fluid_typography( $prepared_post );

$data = json_decode( $result->post_content, true );

$this->assertEquals(
'5.63rem',
$data['settings']['typography']['fontSizes'][0]['size'],
'Global styles should have synced fluid typography sizes'
);
}

/**
* Test that missing typography doesn't cause errors
*/
public function test_sync_with_no_typography() {
$data = array(
'settings' => array(),
);

$result = CBT_Theme_Fluid_Typography::sync_fluid_typography_sizes( $data );

$this->assertArrayNotHasKey( 'typography', $result['settings'] );
$this->assertEqualsCanonicalizing( array(), $result['settings'] );
}

/**
* Test that missing fontSizes doesn't cause errors
*/
public function test_sync_with_no_font_sizes() {
$data = array(
'settings' => array(
'typography' => array(),
),
);

$result = CBT_Theme_Fluid_Typography::sync_fluid_typography_sizes( $data );

$this->assertArrayNotHasKey( 'fontSizes', $result['settings']['typography'] );
}

/**
* Test that invalid JSON in global styles filter is handled gracefully
*/
public function test_sync_global_styles_with_invalid_json() {
$prepared_post = new stdClass();
$prepared_post->post_content = 'invalid json';

$result = CBT_Theme_Fluid_Typography::sync_global_styles_fluid_typography( $prepared_post );

// Should return the prepared post unchanged
$this->assertEquals( 'invalid json', $result->post_content );
}
}