Add upstream
This commit is contained in:
		
							
								
								
									
										537
									
								
								wp-content/plugins/jetpack/modules/shortcodes/recipe.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										537
									
								
								wp-content/plugins/jetpack/modules/shortcodes/recipe.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,537 @@ | ||||
| <?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName | ||||
|  | ||||
| use Automattic\Jetpack\Assets; | ||||
|  | ||||
| /** | ||||
|  * Embed recipe 'cards' in post, with basic styling and print functionality | ||||
|  * | ||||
|  * To Do | ||||
|  * - defaults settings | ||||
|  * - basic styles/themecolor styles | ||||
|  * - validation/sanitization | ||||
|  * - print styles | ||||
|  * | ||||
|  * @package Jetpack | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Register and display Recipes in posts. | ||||
|  */ | ||||
| class Jetpack_Recipes { | ||||
|  | ||||
| 	/** | ||||
| 	 * Have scripts and styles been enqueued already. | ||||
| 	 * | ||||
| 	 * @var bool | ||||
| 	 */ | ||||
| 	private $scripts_and_style_included = false; | ||||
|  | ||||
| 	/** | ||||
| 	 * Constructor | ||||
| 	 */ | ||||
| 	public function __construct() { | ||||
| 		add_action( 'init', array( $this, 'action_init' ) ); | ||||
|  | ||||
| 		add_filter( 'wp_kses_allowed_html', array( $this, 'add_recipes_kses_rules' ), 10, 2 ); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Add Schema-specific attributes to our allowed tags in wp_kses, | ||||
| 	 * so we can have better Schema.org compliance. | ||||
| 	 * | ||||
| 	 * @param array $allowedtags Array of allowed HTML tags in recipes. | ||||
| 	 * @param array $context Context to judge allowed tags by. | ||||
| 	 */ | ||||
| 	public function add_recipes_kses_rules( $allowedtags, $context ) { | ||||
| 		if ( in_array( $context, array( '', 'post', 'data' ) ) ) : // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict | ||||
| 			// Create an array of all the tags we'd like to add the itemprop attribute to. | ||||
| 			$tags = array( 'li', 'ol', 'ul', 'img', 'p', 'h3', 'time' ); | ||||
| 			foreach ( $tags as $tag ) { | ||||
| 				$allowedtags = $this->add_kses_rule( | ||||
| 					$allowedtags, | ||||
| 					$tag, | ||||
| 					array( | ||||
| 						'class'    => array(), | ||||
| 						'itemprop' => array(), | ||||
| 						'datetime' => array(), | ||||
| 					) | ||||
| 				); | ||||
| 			} | ||||
|  | ||||
| 			// Allow itemscope and itemtype for divs. | ||||
| 			$allowedtags = $this->add_kses_rule( | ||||
| 				$allowedtags, | ||||
| 				'div', | ||||
| 				array( | ||||
| 					'class'     => array(), | ||||
| 					'itemscope' => array(), | ||||
| 					'itemtype'  => array(), | ||||
| 				) | ||||
| 			); | ||||
| 		endif; | ||||
|  | ||||
| 		return $allowedtags; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Function to add a new property rule to our kses array. | ||||
| 	 * Used by add_recipe_kses_rules() above. | ||||
| 	 * | ||||
| 	 * @param array  $all_tags Array of allowed HTML tags in recipes. | ||||
| 	 * @param string $tag      New HTML tag to add to the array of allowed HTML. | ||||
| 	 * @param array  $rules    Array of allowed attributes for that HTML tag. | ||||
| 	 */ | ||||
| 	private function add_kses_rule( $all_tags, $tag, $rules ) { | ||||
|  | ||||
| 		// If the tag doesn't already exist, add it. | ||||
| 		if ( ! isset( $all_tags[ $tag ] ) ) { | ||||
| 			$all_tags[ $tag ] = array(); | ||||
| 		} | ||||
|  | ||||
| 		// Merge the new tags with existing tags. | ||||
| 		$all_tags[ $tag ] = array_merge( $all_tags[ $tag ], $rules ); | ||||
|  | ||||
| 		return $all_tags; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Register our shortcode and enqueue necessary files. | ||||
| 	 */ | ||||
| 	public function action_init() { | ||||
| 		// Enqueue styles if [recipe] exists. | ||||
| 		add_action( 'wp_head', array( $this, 'add_scripts' ), 1 ); | ||||
|  | ||||
| 		// Render [recipe], along with other shortcodes that can be nested within. | ||||
| 		add_shortcode( 'recipe', array( $this, 'recipe_shortcode' ) ); | ||||
| 		add_shortcode( 'recipe-notes', array( $this, 'recipe_notes_shortcode' ) ); | ||||
| 		add_shortcode( 'recipe-ingredients', array( $this, 'recipe_ingredients_shortcode' ) ); | ||||
| 		add_shortcode( 'recipe-directions', array( $this, 'recipe_directions_shortcode' ) ); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Enqueue scripts and styles | ||||
| 	 */ | ||||
| 	public function add_scripts() { | ||||
| 		if ( empty( $GLOBALS['posts'] ) || ! is_array( $GLOBALS['posts'] ) ) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		foreach ( $GLOBALS['posts'] as $p ) { | ||||
| 			if ( has_shortcode( $p->post_content, 'recipe' ) ) { | ||||
| 				$this->scripts_and_style_included = true; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if ( ! $this->scripts_and_style_included ) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		wp_enqueue_style( 'jetpack-recipes-style', plugins_url( '/css/recipes.css', __FILE__ ), array(), '20130919' ); | ||||
| 		wp_style_add_data( 'jetpack-recipes-style', 'rtl', 'replace' ); | ||||
|  | ||||
| 		// add $themecolors-defined styles. | ||||
| 		wp_add_inline_style( 'jetpack-recipes-style', self::themecolor_styles() ); | ||||
| 		wp_enqueue_script( | ||||
| 			'jetpack-recipes-printthis', | ||||
| 			Assets::get_file_url_for_environment( '_inc/build/shortcodes/js/recipes-printthis.min.js', 'modules/shortcodes/js/recipes-printthis.js' ), | ||||
| 			array( 'jquery' ), | ||||
| 			'20170202', | ||||
| 			false | ||||
| 		); | ||||
|  | ||||
| 		wp_enqueue_script( | ||||
| 			'jetpack-recipes-js', | ||||
| 			Assets::get_file_url_for_environment( '_inc/build/shortcodes/js/recipes.min.js', 'modules/shortcodes/js/recipes.js' ), | ||||
| 			array( 'jquery', 'jetpack-recipes-printthis' ), | ||||
| 			'20131230', | ||||
| 			false | ||||
| 		); | ||||
|  | ||||
| 		$title_var     = wp_title( '|', false, 'right' ); | ||||
| 		$rtl           = is_rtl() ? '-rtl' : ''; | ||||
| 		$print_css_var = plugins_url( "/css/recipes-print{$rtl}.css", __FILE__ ); | ||||
|  | ||||
| 		wp_localize_script( | ||||
| 			'jetpack-recipes-js', | ||||
| 			'jetpack_recipes_vars', | ||||
| 			array( | ||||
| 				'pageTitle' => $title_var, | ||||
| 				'loadCSS'   => $print_css_var, | ||||
| 			) | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Our [recipe] shortcode. | ||||
| 	 * Prints recipe data styled to look good on *any* theme. | ||||
| 	 * | ||||
| 	 * @param array  $atts    Array of shortcode attributes. | ||||
| 	 * @param string $content Post content. | ||||
| 	 * | ||||
| 	 * @return string HTML for recipe shortcode. | ||||
| 	 */ | ||||
| 	public static function recipe_shortcode( $atts, $content = '' ) { | ||||
| 		$atts = shortcode_atts( | ||||
| 			array( | ||||
| 				'title'       => '', // string. | ||||
| 				'servings'    => '', // intval. | ||||
| 				'time'        => '', // string. | ||||
| 				'difficulty'  => '', // string. | ||||
| 				'print'       => '', // string. | ||||
| 				'source'      => '', // string. | ||||
| 				'sourceurl'   => '', // string. | ||||
| 				'image'       => '', // string. | ||||
| 				'description' => '', // string. | ||||
| 			), | ||||
| 			$atts, | ||||
| 			'recipe' | ||||
| 		); | ||||
|  | ||||
| 		return self::recipe_shortcode_html( $atts, $content ); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * The recipe output | ||||
| 	 * | ||||
| 	 * @param array  $atts    Array of shortcode attributes. | ||||
| 	 * @param string $content Post content. | ||||
| 	 * | ||||
| 	 * @return string HTML output | ||||
| 	 */ | ||||
| 	private static function recipe_shortcode_html( $atts, $content = '' ) { | ||||
|  | ||||
| 		$html = '<div class="hrecipe jetpack-recipe" itemscope itemtype="https://schema.org/Recipe">'; | ||||
|  | ||||
| 		// Print the recipe title if exists. | ||||
| 		if ( '' !== $atts['title'] ) { | ||||
| 			$html .= '<h3 class="jetpack-recipe-title" itemprop="name">' . esc_html( $atts['title'] ) . '</h3>'; | ||||
| 		} | ||||
|  | ||||
| 		// Print the recipe meta if exists. | ||||
| 		if ( | ||||
| 			'' !== $atts['servings'] | ||||
| 			|| '' !== $atts['time'] | ||||
| 			|| '' !== $atts['difficulty'] | ||||
| 			|| '' !== $atts['print'] | ||||
| 		) { | ||||
| 			$html .= '<ul class="jetpack-recipe-meta">'; | ||||
|  | ||||
| 			if ( '' !== $atts['servings'] ) { | ||||
| 				$html .= sprintf( | ||||
| 					'<li class="jetpack-recipe-servings" itemprop="recipeYield"><strong>%1$s: </strong>%2$s</li>', | ||||
| 					esc_html_x( 'Servings', 'recipe', 'jetpack' ), | ||||
| 					esc_html( $atts['servings'] ) | ||||
| 				); | ||||
| 			} | ||||
|  | ||||
| 			if ( '' !== $atts['time'] ) { | ||||
| 				// Get a time that's supported by Schema.org. | ||||
| 				$duration = WPCOM_JSON_API_Date::format_duration( $atts['time'] ); | ||||
| 				// If no duration can be calculated, let's output what the user provided. | ||||
| 				if ( empty( $duration ) ) { | ||||
| 					$duration = $atts['time']; | ||||
| 				} | ||||
|  | ||||
| 				$html .= sprintf( | ||||
| 					'<li class="jetpack-recipe-time"> | ||||
| 					<time itemprop="totalTime" datetime="%3$s"><strong>%1$s: </strong>%2$s</time> | ||||
| 					</li>', | ||||
| 					esc_html_x( 'Time', 'recipe', 'jetpack' ), | ||||
| 					esc_html( $atts['time'] ), | ||||
| 					esc_attr( $duration ) | ||||
| 				); | ||||
| 			} | ||||
|  | ||||
| 			if ( '' !== $atts['difficulty'] ) { | ||||
| 				$html .= sprintf( | ||||
| 					'<li class="jetpack-recipe-difficulty"><strong>%1$s: </strong>%2$s</li>', | ||||
| 					esc_html_x( 'Difficulty', 'recipe', 'jetpack' ), | ||||
| 					esc_html( $atts['difficulty'] ) | ||||
| 				); | ||||
| 			} | ||||
|  | ||||
| 			if ( '' !== $atts['source'] ) { | ||||
| 				$html .= sprintf( | ||||
| 					'<li class="jetpack-recipe-source"><strong>%1$s: </strong>', | ||||
| 					esc_html_x( 'Source', 'recipe', 'jetpack' ) | ||||
| 				); | ||||
|  | ||||
| 				if ( '' !== $atts['sourceurl'] ) : | ||||
| 					// Show the link if we have one. | ||||
| 					$html .= sprintf( | ||||
| 						'<a href="%2$s">%1$s</a>', | ||||
| 						esc_html( $atts['source'] ), | ||||
| 						esc_url( $atts['sourceurl'] ) | ||||
| 					); | ||||
| 				else : | ||||
| 					// Skip the link. | ||||
| 					$html .= sprintf( | ||||
| 						'%1$s', | ||||
| 						esc_html( $atts['source'] ) | ||||
| 					); | ||||
| 				endif; | ||||
|  | ||||
| 				$html .= '</li>'; | ||||
| 			} | ||||
|  | ||||
| 			if ( 'false' !== $atts['print'] ) { | ||||
| 				$html .= sprintf( | ||||
| 					'<li class="jetpack-recipe-print"><a href="#">%1$s</a></li>', | ||||
| 					esc_html_x( 'Print', 'recipe', 'jetpack' ) | ||||
| 				); | ||||
| 			} | ||||
|  | ||||
| 			$html .= '</ul>'; | ||||
| 		} | ||||
|  | ||||
| 		// Output the image, if we have one. | ||||
| 		if ( '' !== $atts['image'] ) { | ||||
| 			$html .= sprintf( | ||||
| 				'<img class="jetpack-recipe-image" itemprop="image" src="%1$s" />', | ||||
| 				esc_url( $atts['image'] ) | ||||
| 			); | ||||
| 		} | ||||
|  | ||||
| 		// Output the description, if we have one. | ||||
| 		if ( '' !== $atts['description'] ) { | ||||
| 			$html .= sprintf( | ||||
| 				'<p class="jetpack-recipe-description" itemprop="description">%1$s</p>', | ||||
| 				esc_html( $atts['description'] ) | ||||
| 			); | ||||
| 		} | ||||
|  | ||||
| 		// Print content between codes. | ||||
| 		$html .= '<div class="jetpack-recipe-content">' . do_shortcode( $content ) . '</div>'; | ||||
|  | ||||
| 		// Close it up. | ||||
| 		$html .= '</div>'; | ||||
|  | ||||
| 		// If there is a recipe within a recipe, remove the shortcode. | ||||
| 		if ( has_shortcode( $html, 'recipe' ) ) { | ||||
| 			remove_shortcode( 'recipe' ); | ||||
| 		} | ||||
|  | ||||
| 		// Sanitize html. | ||||
| 		$html = wp_kses_post( $html ); | ||||
|  | ||||
| 		// Return the HTML block. | ||||
| 		return $html; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Our [recipe-notes] shortcode. | ||||
| 	 * Outputs ingredients, styled in a div. | ||||
| 	 * | ||||
| 	 * @param array  $atts    Array of shortcode attributes. | ||||
| 	 * @param string $content Post content. | ||||
| 	 * | ||||
| 	 * @return string HTML for recipe notes shortcode. | ||||
| 	 */ | ||||
| 	public static function recipe_notes_shortcode( $atts, $content = '' ) { | ||||
| 		$atts = shortcode_atts( | ||||
| 			array( | ||||
| 				'title' => '', // string. | ||||
| 			), | ||||
| 			$atts, | ||||
| 			'recipe-notes' | ||||
| 		); | ||||
|  | ||||
| 		$html = ''; | ||||
|  | ||||
| 		// Print a title if one exists. | ||||
| 		if ( '' !== $atts['title'] ) { | ||||
| 			$html .= '<h4 class="jetpack-recipe-notes-title">' . esc_html( $atts['title'] ) . '</h4>'; | ||||
| 		} | ||||
|  | ||||
| 		$html .= '<div class="jetpack-recipe-notes">'; | ||||
|  | ||||
| 		// Format content using list functionality, if desired. | ||||
| 		$html .= self::output_list_content( $content, 'notes' ); | ||||
|  | ||||
| 		$html .= '</div>'; | ||||
|  | ||||
| 		// Sanitize html. | ||||
| 		$html = wp_kses_post( $html ); | ||||
|  | ||||
| 		// Return the HTML block. | ||||
| 		return $html; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Our [recipe-ingredients] shortcode. | ||||
| 	 * Outputs notes, styled in a div. | ||||
| 	 * | ||||
| 	 * @param array  $atts    Array of shortcode attributes. | ||||
| 	 * @param string $content Post content. | ||||
| 	 * | ||||
| 	 * @return string HTML for recipe ingredients shortcode. | ||||
| 	 */ | ||||
| 	public static function recipe_ingredients_shortcode( $atts, $content = '' ) { | ||||
| 		$atts = shortcode_atts( | ||||
| 			array( | ||||
| 				'title' => esc_html_x( 'Ingredients', 'recipe', 'jetpack' ), // string. | ||||
| 			), | ||||
| 			$atts, | ||||
| 			'recipe-ingredients' | ||||
| 		); | ||||
|  | ||||
| 		$html = '<div class="jetpack-recipe-ingredients">'; | ||||
|  | ||||
| 		// Print a title unless the user has opted to exclude it. | ||||
| 		if ( 'false' !== $atts['title'] ) { | ||||
| 			$html .= '<h4 class="jetpack-recipe-ingredients-title">' . esc_html( $atts['title'] ) . '</h4>'; | ||||
| 		} | ||||
|  | ||||
| 		// Format content using list functionality. | ||||
| 		$html .= self::output_list_content( $content, 'ingredients' ); | ||||
|  | ||||
| 		$html .= '</div>'; | ||||
|  | ||||
| 		// Sanitize html. | ||||
| 		$html = wp_kses_post( $html ); | ||||
|  | ||||
| 		// Return the HTML block. | ||||
| 		return $html; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Reusable function to check for shortened formatting. | ||||
| 	 * Basically, users can create lists with the following shorthand: | ||||
| 	 * - item one | ||||
| 	 * - item two | ||||
| 	 * - item three | ||||
| 	 * And we'll magically convert it to a list. This has the added benefit | ||||
| 	 * of including itemprops for the recipe schema. | ||||
| 	 * | ||||
| 	 * @param string $content HTML content. | ||||
| 	 * @param string $type    Type of list. | ||||
| 	 * | ||||
| 	 * @return string content formatted as a list item | ||||
| 	 */ | ||||
| 	private static function output_list_content( $content, $type ) { | ||||
| 		$html = ''; | ||||
|  | ||||
| 		switch ( $type ) { | ||||
| 			case 'directions': | ||||
| 				$list_item_replacement = '<li class="jetpack-recipe-directions">${1}</li>'; | ||||
| 				$itemprop              = ' itemprop="recipeInstructions"'; | ||||
| 				$listtype              = 'ol'; | ||||
| 				break; | ||||
| 			case 'ingredients': | ||||
| 				$list_item_replacement = '<li class="jetpack-recipe-ingredient" itemprop="recipeIngredient">${1}</li>'; | ||||
| 				$itemprop              = ''; | ||||
| 				$listtype              = 'ul'; | ||||
| 				break; | ||||
| 			default: | ||||
| 				$list_item_replacement = '<li class="jetpack-recipe-notes">${1}</li>'; | ||||
| 				$itemprop              = ''; | ||||
| 				$listtype              = 'ul'; | ||||
| 		} | ||||
|  | ||||
| 		// Check to see if the user is trying to use shortened formatting. | ||||
| 		if ( | ||||
| 			strpos( $content, '–' ) !== false || | ||||
| 			strpos( $content, '—' ) !== false || | ||||
| 			strpos( $content, '-' ) !== false || | ||||
| 			strpos( $content, '*' ) !== false || | ||||
| 			strpos( $content, '#' ) !== false || | ||||
| 			strpos( $content, '–' ) !== false || // ndash. | ||||
| 			strpos( $content, '—' ) !== false || // mdash. | ||||
| 			preg_match( '/\d+\.\s/', $content ) | ||||
| 		) { | ||||
| 			// Remove breaks and extra whitespace. | ||||
| 			$content = str_replace( "<br />\n", "\n", $content ); | ||||
| 			$content = trim( $content ); | ||||
|  | ||||
| 			$ul_pattern = '/(?:^|\n|\<p\>)+(?:[\-–—]+|\–|\—|\*)+\h+(.*)/mi'; | ||||
| 			$ol_pattern = '/(?:^|\n|\<p\>)+(?:\d+\.|#+)+\h+(.*)/mi'; | ||||
|  | ||||
| 			preg_match_all( $ul_pattern, $content, $ul_matches ); | ||||
| 			preg_match_all( $ol_pattern, $content, $ol_matches ); | ||||
|  | ||||
| 			if ( 0 !== count( $ul_matches[0] ) || 0 !== count( $ol_matches[0] ) ) { | ||||
|  | ||||
| 				if ( 0 !== count( $ol_matches[0] ) ) { | ||||
| 					$listtype          = 'ol'; | ||||
| 					$list_item_pattern = $ol_pattern; | ||||
| 				} else { | ||||
| 					$listtype          = 'ul'; | ||||
| 					$list_item_pattern = $ul_pattern; | ||||
| 				} | ||||
| 				$html .= '<' . $listtype . $itemprop . '>'; | ||||
| 				$html .= preg_replace( $list_item_pattern, $list_item_replacement, $content ); | ||||
| 				$html .= '</' . $listtype . '>'; | ||||
|  | ||||
| 				// Strip out any empty <p> tags and stray </p> tags, because those are just silly. | ||||
| 				$empty_p_pattern = '/(<p>)*\s*<\/p>/mi'; | ||||
| 				$html            = preg_replace( $empty_p_pattern, '', $html ); | ||||
| 			} else { | ||||
| 				$html .= do_shortcode( $content ); | ||||
| 			} | ||||
| 		} else { | ||||
| 			$html .= do_shortcode( $content ); | ||||
| 		} | ||||
|  | ||||
| 		// Return our formatted content. | ||||
| 		return $html; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Our [recipe-directions] shortcode. | ||||
| 	 * Outputs directions, styled in a div. | ||||
| 	 * | ||||
| 	 * @param array  $atts    Array of shortcode attributes. | ||||
| 	 * @param string $content Post content. | ||||
| 	 * | ||||
| 	 * @return string HTML for recipe directions shortcode. | ||||
| 	 */ | ||||
| 	public static function recipe_directions_shortcode( $atts, $content = '' ) { | ||||
| 		$atts = shortcode_atts( | ||||
| 			array( | ||||
| 				'title' => esc_html_x( 'Directions', 'recipe', 'jetpack' ), // string. | ||||
| 			), | ||||
| 			$atts, | ||||
| 			'recipe-directions' | ||||
| 		); | ||||
|  | ||||
| 		$html = '<div class="jetpack-recipe-directions">'; | ||||
|  | ||||
| 		// Print a title unless the user has specified to exclude it. | ||||
| 		if ( 'false' !== $atts['title'] ) { | ||||
| 			$html .= '<h4 class="jetpack-recipe-directions-title">' . esc_html( $atts['title'] ) . '</h4>'; | ||||
| 		} | ||||
|  | ||||
| 		// Format content using list functionality. | ||||
| 		$html .= self::output_list_content( $content, 'directions' ); | ||||
|  | ||||
| 		$html .= '</div>'; | ||||
|  | ||||
| 		// Sanitize html. | ||||
| 		$html = wp_kses_post( $html ); | ||||
|  | ||||
| 		// Return the HTML block. | ||||
| 		return $html; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Use $themecolors array to style the Recipes shortcode | ||||
| 	 * | ||||
| 	 * @print style block | ||||
| 	 * @return string $style | ||||
| 	 */ | ||||
| 	public function themecolor_styles() { | ||||
| 		global $themecolors; | ||||
| 		$style = ''; | ||||
|  | ||||
| 		if ( isset( $themecolors ) ) { | ||||
| 			$style .= '.jetpack-recipe { border-color: #' . esc_attr( $themecolors['border'] ) . '; }'; | ||||
| 			$style .= '.jetpack-recipe-title { border-bottom-color: #' . esc_attr( $themecolors['link'] ) . '; }'; | ||||
| 		} | ||||
|  | ||||
| 		return $style; | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| new Jetpack_Recipes(); | ||||
		Reference in New Issue
	
	Block a user