Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
d4f504b
fix: save dynamic post content value
girishpanchal30 Mar 17, 2026
f0e95c5
refactor: update slow animation speed
girishpanchal30 Mar 17, 2026
723894b
fix: check for WP_Post to prevent errors
girishpanchal30 Mar 18, 2026
69b7acf
fix: prevent excerpt infinite loop
girishpanchal30 Mar 19, 2026
d368662
fix: update content retrieval
girishpanchal30 Mar 20, 2026
df0c0d9
Sync branch [skip ci]
pirate-bot Mar 25, 2026
c537372
Sync branch [skip ci]
pirate-bot Mar 25, 2026
79bfde2
fix: sanitize taxonomy filter input in atomic wind blocks
abaicus Mar 25, 2026
07b75cc
Merge branch 'development' of https://github.com/codeinwp/otter-block…
abaicus Mar 25, 2026
3e72b1b
fix: missing authorization in purchase verification
girishpanchal30 Mar 30, 2026
4395af3
fix: improve product id retrieval
girishpanchal30 Mar 30, 2026
7027094
fix: add test for incorrect price ID purchase
girishpanchal30 Mar 30, 2026
af81f79
chore: upgrade SDK to v3.3.51
Mar 30, 2026
609ce94
Merge pull request #2767 from Codeinwp/bugfix/otter-internal/270
vytisbulkevicius Mar 31, 2026
ae3bda2
Merge pull request #2757 from Codeinwp/bugfix/2678
vytisbulkevicius Mar 31, 2026
b077261
Merge pull request #2756 from Codeinwp/bugfix/2618
vytisbulkevicius Mar 31, 2026
86c2552
fix: php undefined array key warning
girishpanchal30 Apr 1, 2026
779830a
fix: handle font variant
girishpanchal30 Apr 1, 2026
7ebde40
Merge pull request #2769 from Codeinwp/bugfix/2768
vytisbulkevicius Apr 1, 2026
4746cdb
Initial plan
Copilot Feb 16, 2026
b587706
Add color slug resolution for advanced-heading block
Copilot Feb 16, 2026
d32169a
Build project successfully with color slug resolution
girishpanchal30 Apr 1, 2026
efb938a
Add useColorResolver hook for easier color slug resolution
Copilot Feb 16, 2026
bf522a5
Add documentation for color slug resolution
Copilot Feb 16, 2026
2ea551f
Fix trailing whitespace issues from code review
Copilot Feb 16, 2026
e08252c
Apply color slug resolution fix to circle-counter, countdown, sharing…
Copilot Feb 16, 2026
ff9a9ad
Apply color slug resolution to high-priority blocks (button, section,…
Copilot Feb 16, 2026
013c0da
Use CSS variables to preserve color slug connection to theme.json
Copilot Feb 19, 2026
c4f3f70
Add slug sanitization and improve documentation clarity
Copilot Feb 19, 2026
75d0ccb
Add comprehensive implementation summary documentation
Copilot Feb 19, 2026
ad981f1
Remove extra documentation and add unit tests for color CSS variable …
Copilot Feb 19, 2026
cd57850
Allow underscores in color slug sanitization per WordPress conventions
Copilot Feb 19, 2026
890c765
Remove color-slug-resolution.md documentation file
Copilot Feb 19, 2026
8079ae9
Fix JSDoc alignment error in helper-functions.js
Copilot Feb 19, 2026
e6c672c
Fix useDarkBackground to handle color slugs properly
Copilot Feb 19, 2026
b66e456
Add robust type checking and error handling to color functions
Copilot Feb 19, 2026
90a6c99
Simplify useColorResolver hook - remove unused palette dependency
Copilot Feb 23, 2026
243efd2
Fix accordion and tabs blocks to use color slug resolution
Copilot Feb 23, 2026
aaca3d9
Fix React Hooks dependencies in accordion block
Copilot Feb 23, 2026
0c7f0b8
Remove unnecessary dependency from useCallback in accordion
Copilot Feb 23, 2026
e008e63
Revert useCallback wrapping of getValue to fix accordion initialization
Copilot Feb 23, 2026
d5e0cf5
Add test infrastructure for e2e tests (emptytheme, wp-env.json)
Copilot Feb 23, 2026
8d9714d
Add comprehensive E2E test setup documentation
Copilot Feb 23, 2026
dda1c64
Revert e2e testing infrastructure additions (already exists in repo)
Copilot Feb 23, 2026
0cceac4
refactor: update black friday labels (#2755)
Soare-Robert-Daniel Apr 1, 2026
3290d41
fix: accordion icon on large title
girishpanchal30 Apr 1, 2026
b1464ab
fix: accordion icon on large title
girishpanchal30 Apr 1, 2026
eab70d3
Merge pull request #2743 from Codeinwp/copilot/fix-color-slugs-in-ott…
vytisbulkevicius Apr 1, 2026
3eb1649
Merge pull request #2770 from Codeinwp/bugfix/1937
vytisbulkevicius Apr 1, 2026
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 composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
},
"minimum-stability": "dev",
"require": {
"codeinwp/themeisle-sdk": "^3.2",
"codeinwp/themeisle-sdk": "^3.3",
"masterminds/html5": "^2.7",
"tubalmartin/cssmin": "^4.1",
"wptt/webfont-loader": "^1.1",
Expand Down
18 changes: 9 additions & 9 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 53 additions & 2 deletions inc/class-base-css.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,11 @@ public function get_google_fonts( $attr ) {
'fontfamily' => $attr['fontFamily'],
'fontvariant' => ( isset( $attr['fontVariant'] ) && ! empty( $attr['fontVariant'] ) ? array( $attr['fontVariant'] ) : array() ),
);
} elseif ( ! in_array( $attr['fontVariant'], self::$google_fonts[ $attr['fontFamily'] ]['fontvariant'], true ) ) {
array_push( self::$google_fonts[ $attr['fontFamily'] ]['fontvariant'], ( isset( $attr['fontStyle'] ) && 'italic' === $attr['fontStyle'] ) ? $attr['fontVariant'] . ':i' : $attr['fontVariant'] );
} elseif ( isset( $attr['fontVariant'] ) && ! empty( $attr['fontVariant'] ) ) {
$font_variant = $attr['fontVariant'];
if ( ! in_array( $font_variant, self::$google_fonts[ $attr['fontFamily'] ]['fontvariant'], true ) ) {
self::$google_fonts[ $attr['fontFamily'] ]['fontvariant'][] = $font_variant;
}
}
}
}
Expand Down Expand Up @@ -199,6 +202,54 @@ public static function hex2rgba( $color, $opacity = false ) {
return $output;
}

/**
* Convert a color slug to a CSS variable reference.
* WordPress generates CSS variables in the format: --wp--preset--color--{slug}
*
* @param string|null $slug The color slug.
* @return string|null The CSS variable reference.
* @since 3.1.5
* @access public
*/
public static function get_color_css_variable( $slug ) {
if ( empty( $slug ) ) {
return $slug;
}

// If it's already a color value or CSS variable, return as-is.
if (
strpos( $slug, '#' ) === 0 ||
strpos( $slug, 'rgb' ) === 0 ||
strpos( $slug, 'hsl' ) === 0 ||
strpos( $slug, 'var(' ) === 0
) {
return $slug;
}

// Sanitize slug: WordPress slugs should only contain lowercase alphanumeric, hyphens, and underscores.
// This prevents potential CSS injection if slug comes from untrusted sources.
$sanitized_slug = strtolower( preg_replace( '/[^a-z0-9-_]/', '', $slug ) );

// Convert slug to CSS variable.
return 'var(--wp--preset--color--' . $sanitized_slug . ')';
}

/**
* Resolve a color value which may be a slug from the theme color palette.
* This function converts slugs to CSS variables to preserve the connection to theme.json.
* If the value is a slug, it returns a CSS variable reference.
* Otherwise, returns the value as-is (for hex, rgb, hsl values).
*
* @param string|null $value The color value or slug.
* @return string|null The CSS variable or color value.
* @since 3.1.5
* @access public
*/
public static function resolve_color_value( $value ) {
// Use CSS variable conversion for slugs.
return self::get_color_css_variable( $value );
}

/**
* Get Blocks CSS
*
Expand Down
54 changes: 38 additions & 16 deletions inc/class-main.php
Original file line number Diff line number Diff line change
Expand Up @@ -599,30 +599,52 @@ public function about_page() {
public function add_black_friday_data( $configs ) {
$config = $configs['default'];

// translators: %1$s - HTML tag, %2$s - discount, %3$s - HTML tag, %4$s - product name.
$message_template = __( 'Our biggest sale of the year: %1$sup to %2$s OFF%3$s on %4$s. Don\'t miss this limited-time offer.', 'otter-blocks' );
$product_label = 'Otter Blocks';
$discount = '70%';
$message = __( 'Advanced blocks, custom CSS, WooCommerce integration. Everything you need to build better pages, without code. Exclusively for existing Otter users.', 'otter-blocks' );
$cta_label = __( 'Get Otter Pro', 'otter-blocks' );

$plan = apply_filters( 'product_otter_license_plan', 0 );
$license = apply_filters( 'product_otter_license_key', false );
$is_pro = 0 < $plan;
$status = apply_filters( 'product_otter_license_status', false );

$is_pro = 'valid' === $status;
$is_expired = 'expired' === $status || 'active-expired' === $status;
$pro_product_slug = defined( 'OTTER_PRO_BASEFILE' ) ? basename( dirname( OTTER_PRO_BASEFILE ) ) : '';

if ( $is_pro ) {
// translators: %1$s - HTML tag, %2$s - discount, %3$s - HTML tag, %4$s - product name.
$message_template = __( 'Get %1$sup to %2$s off%3$s when you upgrade your %4$s plan or renew early.', 'otter-blocks' );
$product_label = 'Otter Pro';
$discount = '30%';
}

$product_label = sprintf( '<strong>%s</strong>', $product_label );
$url_params = array(
// translators: %s is the discount percentage.
$config['plugin_meta_message'] = sprintf( __( 'Black Friday Sale - up to %s off', 'otter-blocks' ), '30%' );
// translators: %1$s - discount, %2$s - discount.
$message = sprintf( __( 'Upgrade your Otter Pro plan: %1$s off this week. Already on the plan you need? Renew early and save up to %2$s.', 'otter-blocks' ), '30%', '20%' );
$cta_label = __( 'See your options', 'otter-blocks' );
} elseif ( $is_expired ) {
// translators: %s is the discount percentage.
$config['plugin_meta_message'] = sprintf( __( 'Black Friday Sale - %s off', 'otter-blocks' ), '50%' );
// translators: %s is the discount percentage.
$config['upgrade_menu_text'] = sprintf( __( 'BF Sale - %s off', 'otter-blocks' ), '50%' );
$message = __( 'Your Otter Pro features are still here, just locked. Renew at a reduced rate this week.', 'otter-blocks' );
$cta_label = __( 'Reactivate now', 'otter-blocks' );
} else {
// translators: %s is the discount percentage.
$config['plugin_meta_message'] = sprintf( __( 'Black Friday Sale - %s off', 'otter-blocks' ), '60%' );
// translators: %s is the discount percentage.
$config['upgrade_menu_text'] = sprintf( __( 'BF Sale - %s off', 'otter-blocks' ), '60%' );
// translators: %s - discount.
$config['title'] = sprintf( __( 'Otter Pro: %s off this week', 'otter-blocks' ), '60%' );
}

$url_params = array(
'utm_term' => $is_pro ? 'plan-' . $plan : 'free',
'lkey' => ! empty( $license ) ? $license : false,
'expired' => $is_expired ? '1' : false,
);

$config['message'] = sprintf( $message_template, '<strong>', $discount, '</strong>', $product_label );
$config['sale_url'] = add_query_arg(

if ( ( $is_pro || $is_expired ) && ! empty( $pro_product_slug ) ) {
$config['plugin_meta_targets'] = array( $pro_product_slug );
}

$config['cta_label'] = $cta_label;
$config['message'] = $message;
$config['sale_url'] = add_query_arg(
$url_params,
tsdk_translate_link( tsdk_utmify( 'https://themeisle.link/otter-bf', 'bfcm', 'otter' ) )
);
Expand Down
3 changes: 3 additions & 0 deletions inc/css/blocks/class-advanced-column-css.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ function ( $value ) use ( $block ) {
array(
'property' => '--background-color-hover',
'value' => 'backgroundColorHover',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'align-self',
Expand Down
18 changes: 18 additions & 0 deletions inc/css/blocks/class-advanced-heading-css.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,16 @@ public function render_css( $block ) {
array(
'property' => 'color',
'value' => 'headingColor',
'format' => function ( $value, $attrs ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'background',
'value' => 'backgroundColor',
'format' => function ( $value, $attrs ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'font-family',
Expand Down Expand Up @@ -225,10 +231,16 @@ public function render_css( $block ) {
array(
'property' => 'color',
'value' => 'highlightColor',
'format' => function ( $value, $attrs ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'background',
'value' => 'highlightBackground',
'format' => function ( $value, $attrs ) {
return Base_CSS::resolve_color_value( $value );
},
),
);

Expand Down Expand Up @@ -537,6 +549,9 @@ public function render_css( $block ) {
array(
'property' => 'color',
'value' => 'linkColor',
'format' => function ( $value, $attrs ) {
return Base_CSS::resolve_color_value( $value );
},
),
),
)
Expand All @@ -549,6 +564,9 @@ public function render_css( $block ) {
array(
'property' => 'color',
'value' => 'linkHoverColor',
'format' => function ( $value, $attrs ) {
return Base_CSS::resolve_color_value( $value );
},
),
),
)
Expand Down
36 changes: 36 additions & 0 deletions inc/css/blocks/class-button-css.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,17 @@ public function render_css( $block ) {
'property' => 'color',
'value' => 'color',
'hasSync' => 'gr-btn-color',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'background',
'value' => 'background',
'hasSync' => 'gr-btn-background',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'background',
Expand All @@ -150,6 +156,9 @@ public function render_css( $block ) {
'property' => 'border-color',
'value' => 'border',
'hasSync' => 'gr-btn-border-color',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'box-shadow',
Expand Down Expand Up @@ -201,11 +210,17 @@ public function render_css( $block ) {
'property' => 'color',
'value' => 'hoverColor',
'hasSync' => 'gr-btn-color-hover',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'background',
'value' => 'hoverBackground',
'hasSync' => 'gr-btn-background-hover',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'background',
Expand All @@ -216,6 +231,9 @@ public function render_css( $block ) {
'property' => 'border-color',
'value' => 'hoverBorder',
'hasSync' => 'gr-btn-border-color-hover',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => 'box-shadow',
Expand Down Expand Up @@ -298,10 +316,16 @@ public function render_global_css() {
array(
'property' => '--gr-btn-color',
'value' => 'color',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => '--gr-btn-background',
'value' => 'background',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => '--gr-btn-background',
Expand Down Expand Up @@ -336,6 +360,9 @@ public function render_global_css() {
array(
'property' => '--gr-btn-border-color',
'value' => 'border',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
'condition' => function ( $attrs ) {
return isset( $attrs['border'] ) && ! empty( $attrs['border'] );
},
Expand Down Expand Up @@ -421,10 +448,16 @@ public function render_global_css() {
array(
'property' => '--gr-btn-color-hover',
'value' => 'hoverColor',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => '--gr-btn-background-hover',
'value' => 'hoverBackground',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => '--gr-btn-background-hover',
Expand All @@ -433,6 +466,9 @@ public function render_global_css() {
array(
'property' => '--gr-btn-border-color-hover',
'value' => 'hoverBorder',
'format' => function ( $value ) {
return Base_CSS::resolve_color_value( $value );
},
),
array(
'property' => '--gr-btn-shadow-hover',
Expand Down
Loading
Loading