diff --git a/projects/packages/search/changelog/add-inline-search-branding b/projects/packages/search/changelog/add-inline-search-branding new file mode 100644 index 0000000000000..3630b8beef243 --- /dev/null +++ b/projects/packages/search/changelog/add-inline-search-branding @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Inline Search: add Jetpack Branding to search results. diff --git a/projects/packages/search/changelog/add-inline-search-term-highlighting b/projects/packages/search/changelog/add-inline-search-term-highlighting new file mode 100644 index 0000000000000..e8bd7beb03ccb --- /dev/null +++ b/projects/packages/search/changelog/add-inline-search-term-highlighting @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Add highlighting of search term in returned search results. diff --git a/projects/packages/search/src/inline-search/class-inline-search-colophon.php b/projects/packages/search/src/inline-search/class-inline-search-colophon.php new file mode 100644 index 0000000000000..aedc367069a1b --- /dev/null +++ b/projects/packages/search/src/inline-search/class-inline-search-colophon.php @@ -0,0 +1,155 @@ +is_valid_search_query( $query ) ) { + return; + } + + add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) ); + add_action( 'wp_footer', array( $this, 'register_colophon_script' ) ); + } + + /** + * Enqueue theme-specific styles for the search colophon. + * This is hooked to wp_enqueue_scripts to ensure styles load properly in the head. + * + * @since $$next-version$$ + */ + public function enqueue_styles() { + $handle = 'jetpack-search-inline-colophon'; + $this->register_component_style( $handle, 'colophon.css' ); + } + + /** + * Register and configure the JavaScript for displaying the colophon. + * + * @since $$next-version$$ + */ + public function register_colophon_script() { + $this->register_inline_search_script(); + + // Don't localize if already localized to prevent duplication + if ( wp_script_is( self::SCRIPT_HANDLE, 'data' ) ) { + $localized_data = wp_scripts()->get_data( self::SCRIPT_HANDLE, 'data' ); + if ( $localized_data && strpos( $localized_data, 'JetpackSearchColophon' ) !== false ) { + return; + } + } + + // Only localize the script, don't register it again as it's handled by the base class + wp_localize_script( + self::SCRIPT_HANDLE, + 'JetpackSearchColophon', + array( + 'html' => $this->get_colophon_html(), + 'selector' => $this->format_selectors_for_query( $this->get_content_selectors() ), + ) + ); + } + + /** + * Get selectors where colophon will be displayed. + * + * @since $$next-version$$ + * @return array CSS selectors for content container elements. + */ + private function get_content_selectors() { + $default_selectors = array( + '.wp-block-query', + '.content', + '#content', + '#site-content', + '.site-main', + '.content-area', + ); + + /** + * Filter the selectors where colophon appears. + * + * @since $$next-version$$ + * @param array $default_selectors CSS selectors for content container elements. + */ + return apply_filters( 'jetpack_search_colophon_selectors', $default_selectors ); + } + + /** + * Get the locale for the Jetpack URL. + * + * @return string|null The locale prefix or null. + */ + private function get_locale_prefix() { + $locale = get_locale(); + if ( empty( $locale ) ) { + return null; + } + + $locale_prefix = explode( '-', $locale )[0]; + return $locale_prefix !== 'en' ? $locale_prefix : null; + } + + /** + * Generate the HTML for the colophon. + * + * @return string The HTML for the colophon. + */ + private function get_colophon_html() { + $locale_prefix = $this->get_locale_prefix(); + $url = $locale_prefix + ? 'https://' . $locale_prefix . '.jetpack.com/upgrade/search?utm_source=poweredby' + : 'https://jetpack.com/upgrade/search/?utm_source=poweredby'; + + $logo_svg = $this->get_logo_svg(); + + return sprintf( + '
+ + %s + %s + +
', + esc_url( $url ), + $logo_svg, + esc_html__( 'Search powered by Jetpack', 'jetpack-search-pkg' ) + ); + } + + /** + * Get the SVG markup for the Jetpack logo. + * + * @return string The SVG markup. + */ + private function get_logo_svg() { + $color_jetpack = '#069E08'; + $color_white = '#ffffff'; + $logo_size = 12; + + return sprintf( + '', + $logo_size, + $color_jetpack, + $color_white + ); + } +} diff --git a/projects/packages/search/src/inline-search/class-inline-search-component.php b/projects/packages/search/src/inline-search/class-inline-search-component.php new file mode 100644 index 0000000000000..763d6dfe9a2fb --- /dev/null +++ b/projects/packages/search/src/inline-search/class-inline-search-component.php @@ -0,0 +1,113 @@ +is_search() && $query->is_main_query(); + } + + /** + * Register and enqueue a component stylesheet. + * + * @since $$next-version$$ + * @param string $handle The script handle to use for the stylesheet. + * @param string $css_file The CSS filename (without the path). + * @return bool Whether the style was successfully registered and enqueued. + */ + protected function register_component_style( $handle, $css_file ) { + $css_path = 'build/inline-search/'; + $full_css_path = $css_path . $css_file; + $package_path = Package::get_installed_path(); + $css_full_path = $package_path . '/' . $full_css_path; + + // Verify the CSS file exists before trying to enqueue it + if ( ! file_exists( $css_full_path ) ) { + return false; + } + + // We need to use plugins_url for reliable URL generation + $file_url = plugins_url( + $full_css_path, + $package_path . '/package.json' + ); + + // Use the file's modification time for more precise cache busting + $file_version = file_exists( $css_full_path ) ? filemtime( $css_full_path ) : Package::VERSION; + + wp_enqueue_style( + $handle, + $file_url, + array(), + $file_version // Use file modification time for cache busting + ); + + return true; + } + + /** + * Register the common inline search script if not already registered. + * + * @since $$next-version$$ + * @return bool Whether the script was registered. + */ + protected function register_inline_search_script() { + if ( wp_script_is( self::SCRIPT_HANDLE, 'registered' ) ) { + return true; + } + + return Assets::register_script( + self::SCRIPT_HANDLE, + 'build/inline-search/jp-search-inline.js', + Package::get_installed_path() . '/src', + array( + 'in_footer' => true, + 'textdomain' => 'jetpack-search-pkg', + 'enqueue' => true, + ) + ); + } + + /** + * Get the search result from the Inline_Search instance. + * + * @return array|null The search result or null if not available. + */ + protected function get_search_result() { + $inline_search = Inline_Search::instance(); + return $inline_search->get_search_result(); + } + + /** + * Convert an array of selectors to a comma-separated string for querySelector. + * + * @param array $selectors Array of CSS selectors. + * @return string Comma-separated string of selectors. + */ + protected function format_selectors_for_query( $selectors ) { + return implode( ', ', $selectors ); + } +} diff --git a/projects/packages/search/src/inline-search/class-inline-search-correction.php b/projects/packages/search/src/inline-search/class-inline-search-correction.php index cfb306e8755bc..2d3d74bea4de1 100644 --- a/projects/packages/search/src/inline-search/class-inline-search-correction.php +++ b/projects/packages/search/src/inline-search/class-inline-search-correction.php @@ -7,21 +7,19 @@ namespace Automattic\Jetpack\Search; -use Automattic\Jetpack\Assets; - /** * Class for handling search correction display * * @since $$next-version$$ */ -class Inline_Search_Correction { +class Inline_Search_Correction extends Inline_Search_Component { /** * Setup hooks for displaying corrected query notice. * * @param \WP_Query $query The current query. */ public function setup_corrected_query_hooks( $query ) { - if ( ! $query->is_search() || ! $query->is_main_query() ) { + if ( ! $this->is_valid_search_query( $query ) ) { return; } @@ -42,8 +40,8 @@ public function enqueue_styles() { return; } - $handle = 'jetpack-search-inline-corrected-query'; - $this->register_corrected_query_style( $handle ); + $handle = self::SCRIPT_HANDLE . '-corrected-query'; + $this->register_component_style( $handle, 'corrected-query.css' ); } /** @@ -57,21 +55,20 @@ public function register_corrected_query_script() { return; } - $handle = 'jetpack-search-inline-corrected-query'; + $handle = self::SCRIPT_HANDLE . '-corrected-query'; - Assets::register_script( - $handle, - 'build/inline-search/jp-search-inline.js', - Package::get_installed_path() . '/src', - array( - 'in_footer' => true, - 'textdomain' => 'jetpack-search-pkg', - 'enqueue' => true, - ) - ); + // Don't localize if already localized to prevent duplication + if ( wp_script_is( $handle, 'data' ) ) { + $localized_data = wp_scripts()->get_data( $handle, 'data' ); + if ( $localized_data && strpos( $localized_data, 'JetpackSearchCorrectedQuery' ) !== false ) { + return; + } + } + + $this->register_inline_search_script(); wp_localize_script( - $handle, + self::SCRIPT_HANDLE, 'JetpackSearchCorrectedQuery', array( 'html' => $corrected_query_html, @@ -83,41 +80,6 @@ public function register_corrected_query_script() { ); } - /** - * Register and enqueue theme-specific styles for corrected query. - * - * @since $$next-version$$ - * @param string $handle The script handle to use for the stylesheet. - */ - private function register_corrected_query_style( $handle ) { - $css_path = 'build/inline-search/'; - $css_file = 'corrected-query.css'; - $full_css_path = $css_path . $css_file; - $package_path = Package::get_installed_path(); - $css_full_path = $package_path . '/' . $full_css_path; - - // Verify the CSS file exists before trying to enqueue it - if ( ! file_exists( $css_full_path ) ) { - return; - } - - // We need to use plugins_url for reliable URL generation - $file_url = plugins_url( - $full_css_path, - $package_path . '/package.json' - ); - - // Use the file's modification time for more precise cache busting - $file_version = file_exists( $css_full_path ) ? filemtime( $css_full_path ) : Package::VERSION; - - wp_enqueue_style( - $handle, - $file_url, - array(), - $file_version // Use file modification time for cache busting - ); - } - /** * Replaces the search query with the corrected query in the title. * @@ -183,14 +145,4 @@ private function get_corrected_query_html() { $message ); } - - /** - * Get the search result from the Inline_Search instance. - * - * @return array|\WP_Error|null The search result or null if not available. - */ - private function get_search_result() { - $inline_search = Inline_Search::instance(); - return $inline_search->get_search_result(); - } } diff --git a/projects/packages/search/src/inline-search/class-inline-search-highlighter.php b/projects/packages/search/src/inline-search/class-inline-search-highlighter.php new file mode 100644 index 0000000000000..489ade9fae6aa --- /dev/null +++ b/projects/packages/search/src/inline-search/class-inline-search-highlighter.php @@ -0,0 +1,206 @@ +search_result_ids = $search_result_ids; + $this->highlighted_content = array(); + + // Process API results immediately if provided + if ( $results !== null ) { + $this->process_results( $results ); + } + } + + /** + * Set up the WordPress filters for highlighting. + */ + public function setup() { + add_filter( 'the_title', array( $this, 'filter_highlighted_title' ), 10, 2 ); + add_filter( 'the_content', array( $this, 'filter_highlighted_content' ), 10, 1 ); + add_filter( 'comment_text', array( $this, 'filter_highlighted_comment' ), 10, 2 ); + } + + /** + * Process highlighting data for search results. + * + * @param array $results The search result data from the API. + */ + public function process_results( $results ) { + $this->highlighted_content = array(); + + if ( empty( $results ) || ! is_array( $results ) ) { + return; + } + + foreach ( $results as $result ) { + $post_id = (int) ( $result['fields']['post_id'] ?? 0 ); + $this->process_result_highlighting( $result, $post_id ); + } + } + + /** + * Update search result IDs. + * + * @param array $search_result_ids Array of post IDs from search results. + */ + public function update_search_data( $search_result_ids = array() ) { + $this->search_result_ids = $search_result_ids; + } + + /** + * Filter the post title to show highlighted version. + * + * @param string $title The post title. + * @param int $post_id The post ID. + * @return string The filtered title. + */ + public function filter_highlighted_title( $title, $post_id ) { + if ( ! $this->is_search_result( $post_id ) ) { + return $title; + } + + if ( ! empty( $this->highlighted_content[ $post_id ]['title'] ) ) { + return $this->highlighted_content[ $post_id ]['title']; + } + + return $title; + } + + /** + * Filter the post content to show highlighted version. + * + * @param string $content The post content. + * @return string The filtered content. + */ + public function filter_highlighted_content( $content ) { + $post_id = get_the_ID(); + + if ( ! $this->is_search_result( $post_id ) ) { + return $content; + } + + if ( ! empty( $this->highlighted_content[ $post_id ]['content'] ) ) { + // Apply wpautop to maintain paragraph formatting. + return wpautop( $this->highlighted_content[ $post_id ]['content'] ); + } + + return $content; + } + + /** + * Filter comment text to show highlighted version. + * + * @param string $comment_text The comment text. + * @return string The filtered comment text. + */ + public function filter_highlighted_comment( $comment_text ) { + if ( ! is_search() || ! in_the_loop() ) { + return $comment_text; + } + + $post_id = get_the_ID(); + + if ( ! $this->is_search_result( $post_id ) || empty( $this->highlighted_content[ $post_id ]['comments'] ) ) { + return $comment_text; + } + + return $this->highlighted_content[ $post_id ]['comments']; + } + + /** + * Process highlighting data for a single search result. + * + * @param array $result The search result data from the API. + * @param int $post_id The post ID for this result. + */ + private function process_result_highlighting( $result, $post_id ) { + if ( empty( $result['highlight'] ) ) { + return; + } + + $title = $this->extract_highlight_field( $result, 'title' ); + $content = $this->extract_highlight_field( $result, 'content' ); + $comments = $this->extract_highlight_field( $result, 'comments' ); + + $this->highlighted_content[ $post_id ] = array( + 'title' => $title, + 'content' => $content, + 'comments' => $comments, + ); + } + + /** + * Extract a highlight field from the search result, handling different field formats. + * + * @param array $result The search result data from the API. + * @param string $field The field name to extract. + * @return string The extracted highlighted field. + */ + private function extract_highlight_field( $result, $field ) { + // Try exact match first + if ( isset( $result['highlight'][ $field ] ) && is_array( $result['highlight'][ $field ] ) && ! empty( $result['highlight'][ $field ] ) ) { + return $result['highlight'][ $field ][0]; + } + + // Try field variants with suffixes (e.g., 'title.default') + foreach ( $result['highlight'] as $key => $value ) { + if ( strpos( $key, $field . '.' ) === 0 ) { + if ( is_array( $value ) && ! empty( $value ) ) { + return $value[0]; + } + } + } + + return ''; + } + + /** + * Check if the current post is a search result from our API + * + * @param int $post_id The post ID to check. + * @return bool Whether the post is a search result. + */ + private function is_search_result( $post_id ) { + return is_search() && in_the_loop() && ! empty( $this->search_result_ids ) && in_array( $post_id, $this->search_result_ids, true ); + } + + /** + * Get the highlighted content for a post. + * + * @param int $post_id The post ID. + * @return array|null The highlighted content array or null if not found. + */ + public function get_highlighted_content( $post_id ) { + return $this->highlighted_content[ $post_id ] ?? null; + } +} diff --git a/projects/packages/search/src/inline-search/class-inline-search.php b/projects/packages/search/src/inline-search/class-inline-search.php index 7e99bbd1b02a2..9d1dd132987d8 100644 --- a/projects/packages/search/src/inline-search/class-inline-search.php +++ b/projects/packages/search/src/inline-search/class-inline-search.php @@ -18,13 +18,36 @@ class Inline_Search extends Classic_Search { */ private static $instance; + /** + * The Search Highlighter instance. + * + * @var Inline_Search_Highlighter|null + * @since $$next-version$$ + */ + private $highlighter; + /** * The search correction instance. * - * @var Inline_Search_Correction + * @var Inline_Search_Correction|null + * @since $$next-version$$ */ private $correction; + /** + * The colophon instance. + * + * @var Inline_Search_Colophon + */ + private $colophon; + + /** + * Stores the list of post IDs that are actual search results. + * + * @var array + */ + private $search_result_ids = array(); + /** * Returns whether this class should be used instead of Classic_Search. */ @@ -50,8 +73,14 @@ public static function instance( $blog_id = null ) { // Initialize search correction handling self::$instance->correction = new Inline_Search_Correction(); - // Add hooks for displaying corrected query notice + // Initialize colophon handling + self::$instance->colophon = new Inline_Search_Colophon(); + + // Add hooks for displaying corrected query notice - only once add_action( 'pre_get_posts', array( self::$instance->correction, 'setup_corrected_query_hooks' ) ); + + // Add hooks for displaying the Jetpack colophon - only once + add_action( 'pre_get_posts', array( self::$instance->colophon, 'setup_colophon_hooks' ) ); } return self::$instance; @@ -72,6 +101,17 @@ public static function get_instance_maybe_fallback_to_classic( $blog_id = null ) } } + /** + * Set up the highlighter. + * + * @param string $blog_id The blog ID to set up for. + */ + public function setup( $blog_id ) { + parent::setup( $blog_id ); + // The highlighter will be initialized with data during search processing + $this->highlighter = null; + } + /** * Bypass WP search and offload it to 1.3 search API instead. * @@ -102,24 +142,11 @@ public function filter__posts_pre_query( $posts, $query ) { return array(); } - $post_ids = array(); + // Process the search results to extract post IDs and highlighted content. + $this->process_search_results(); - foreach ( $this->search_result['results'] as $result ) { - $post_ids[] = (int) ( $result['fields']['post_id'] ?? 0 ); - } - - // Query all posts now. - $args = array( - 'post__in' => $post_ids, - 'orderby' => 'post__in', - 'perm' => 'readable', - 'post_type' => 'any', - 'ignore_sticky_posts' => true, - 'suppress_filters' => true, - 'posts_per_page' => $query->get( 'posts_per_page' ), - ); - - $posts_query = new \WP_Query( $args ); + // Create a WP_Query to fetch the actual posts. + $posts_query = $this->create_posts_query( $query ); // WP Core doesn't call the set_found_posts and its filters when filtering posts_pre_query like we do, so need to do these manually. $query->found_posts = $this->found_posts; @@ -314,16 +341,31 @@ public function convert_wp_query_to_api_args( array $args ) { } } + $highlight_fields = array( + 'title', + 'content', + 'comments', + ); + + $fields = array( + 'blog_id', + 'post_id', + 'title', + 'content', + 'comments', + ); + return array( - 'blog_id' => $this->jetpack_blog_id, - 'size' => absint( $args['posts_per_page'] ), - 'from' => min( $from, Helper::get_max_offset() ), - 'fields' => array( 'blog_id', 'post_id' ), - 'query' => $args['query'] ?? '', - 'sort' => $sort, - 'aggregations' => empty( $aggregations ) ? null : $aggregations, - 'langs' => $this->get_langs(), - 'filter' => array( + 'blog_id' => $this->jetpack_blog_id, + 'size' => absint( $args['posts_per_page'] ), + 'from' => min( $from, Helper::get_max_offset() ), + 'fields' => $fields, + 'highlight_fields' => $highlight_fields, + 'query' => $args['query'] ?? '', + 'sort' => $sort, + 'aggregations' => empty( $aggregations ) ? null : $aggregations, + 'langs' => $this->get_langs(), + 'filter' => array( 'bool' => array( 'must' => $this->build_es_filters( $args ), ), @@ -434,4 +476,61 @@ public function get_search_result( ) { return $this->search_result; } + + /** + * Process search results to extract post IDs and highlighted content. + */ + private function process_search_results() { + $post_ids = array(); + $highlighted_results = array(); + + foreach ( $this->search_result['results'] as $result ) { + $post_id = (int) ( $result['fields']['post_id'] ?? 0 ); + $post_ids[] = $post_id; + + // Collect highlight data for processing + if ( ! empty( $result['highlight'] ) ) { + $highlighted_results[ $post_id ] = $result['highlight']; + } + } + + $this->search_result_ids = $post_ids; + $this->highlighter = new Inline_Search_Highlighter( $post_ids ); + + if ( ! empty( $highlighted_results ) ) { + // Format highlight data for the highlighter + $processed_results = array(); + foreach ( $highlighted_results as $post_id => $highlight_data ) { + $processed_results[] = array( + 'fields' => array( + 'post_id' => $post_id, + ), + 'highlight' => $highlight_data, + ); + } + $this->highlighter->process_results( $processed_results ); + } + + $this->highlighter->setup(); + } + + /** + * Create a WP_Query to fetch the posts for search results. + * + * @param \WP_Query $original_query The original WP_Query. + * @return \WP_Query The new query with posts matching the search results. + */ + private function create_posts_query( $original_query ) { + $args = array( + 'post__in' => $this->search_result_ids, + 'orderby' => 'post__in', + 'perm' => 'readable', + 'post_type' => 'any', + 'ignore_sticky_posts' => true, + 'suppress_filters' => true, + 'posts_per_page' => $original_query->get( 'posts_per_page' ), + ); + + return new \WP_Query( $args ); + } } diff --git a/projects/packages/search/src/inline-search/js/corrected-query.js b/projects/packages/search/src/inline-search/js/corrected-query.js deleted file mode 100644 index 94357dba61242..0000000000000 --- a/projects/packages/search/src/inline-search/js/corrected-query.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Script to display corrected query notice after search titles. - */ -document.addEventListener( 'DOMContentLoaded', () => { - if ( ! window.JetpackSearchCorrectedQuery?.html ) { - return; - } - - const { selectors, html } = window.JetpackSearchCorrectedQuery; - const titleElement = document.querySelector( selectors.join( ', ' ) ); - - if ( ! titleElement ) { - return; - } - - titleElement.insertAdjacentHTML( 'afterend', html ); -} ); diff --git a/projects/packages/search/src/inline-search/js/index.js b/projects/packages/search/src/inline-search/js/index.js index ef0d042935a09..43434b34f8966 100644 --- a/projects/packages/search/src/inline-search/js/index.js +++ b/projects/packages/search/src/inline-search/js/index.js @@ -1,6 +1,6 @@ /** * Entry point for inline search styles. - * This file imports the CSS and the modules for inline search. + * This file imports the modules for inline search. */ -import '../styles/corrected-query.scss'; -import './corrected-query'; +import '../styles/index.scss'; +import './inline-search'; diff --git a/projects/packages/search/src/inline-search/js/inline-search.js b/projects/packages/search/src/inline-search/js/inline-search.js new file mode 100644 index 0000000000000..92fb435f02c84 --- /dev/null +++ b/projects/packages/search/src/inline-search/js/inline-search.js @@ -0,0 +1,28 @@ +/** + * Script to display corrected query notice after search titles and colophon at the bottom of search results. + */ +document.addEventListener( 'DOMContentLoaded', () => { + // Handle corrected query display + if ( window.JetpackSearchCorrectedQuery?.html ) { + const { selectors, html } = window.JetpackSearchCorrectedQuery; + const titleElement = document.querySelector( selectors.join( ', ' ) ); + // Check if corrected query element already exists to prevent duplication + const correctedQueryExists = document.querySelector( '.jetpack-search-corrected-query' ); + + if ( titleElement && ! correctedQueryExists ) { + titleElement.insertAdjacentHTML( 'afterend', html ); + } + } + + // Handle colophon display + if ( window.JetpackSearchColophon?.html ) { + const { selector, html } = window.JetpackSearchColophon; + const contentElement = document.querySelector( selector ); + // Check if colophon element already exists to prevent duplication + const colophonExists = document.querySelector( '.jetpack-search-inline-colophon' ); + + if ( contentElement && ! colophonExists ) { + contentElement.insertAdjacentHTML( 'beforeend', html ); + } + } +} ); diff --git a/projects/packages/search/src/inline-search/styles/colophon.scss b/projects/packages/search/src/inline-search/styles/colophon.scss new file mode 100644 index 0000000000000..ae822c9667000 --- /dev/null +++ b/projects/packages/search/src/inline-search/styles/colophon.scss @@ -0,0 +1,135 @@ +$colophon-color: #555; +$colophon-hover-color: #069E08; +$colophon-margin-top: 2rem; +$colophon-margin-bottom: 2rem; +$colophon-padding-top: 1rem; +$colophon-padding-bottom: 1rem; +$colophon-font-size: 0.8rem; +$colophon-logo-margin-right: 4px; + +.jetpack-search-inline-colophon { + display: flex; + justify-content: center; + margin-top: $colophon-margin-top; + margin-bottom: $colophon-margin-bottom; + padding-top: $colophon-padding-top; + padding-bottom: $colophon-padding-bottom; + font-size: $colophon-font-size; + + &-link { + display: flex; + align-items: center; + text-decoration: none; + color: $colophon-color; + + &:hover { + color: $colophon-hover-color; + } + } + + &-logo { + margin-right: $colophon-logo-margin-right; + } +} + +.wp-theme-pubdara, +.wp-theme-dara-wpcom, +.wp-theme-radcliffe-2-wpcom, +.wp-theme-pubradcliffe, +.wp-theme-twentyfifteen, +.wp-theme-pubtwentyfifteen, +.wp-theme-twentytwenty, +.wp-theme-pubtwentytwenty, +.wp-theme-oceanwp { + + .jetpack-search-inline-colophon { + font-size: 1.25rem; + } +} + +.wp-theme-varia-wpcom, +.wp-theme-pubvaria, +.wp-theme-lodestar-wpcom, +.wp-theme-publodestar, +.wp-theme-creatio-2-wpcom, +.wp-theme-pubcreatio-2, +.wp-theme-twentytwentythree, +.wp-theme-pubtwentytwentythree, +.wp-theme-twentytwentyfour, +.wp-theme-pubtwentytwentyfour { + + .jetpack-search-inline-colophon { + justify-content: flex-start; + } +} + +.wp-theme-varia-wpcom, +.wp-theme-pubvaria { + + @media only screen and (min-width: 768px) { + + .jetpack-search-inline-colophon { + margin: 0 auto; + max-width: calc(782px - 32px); + } + } +} + +.wp-theme-twentysixteen, +.wp-theme-pubtwentysixteen { + + .jetpack-search-inline-colophon { + margin-top: 0; + padding-top: 0; + + @media screen and (min-width: 56.875em) { + float: left; + justify-content: flex-start; + margin-right: -100px; + width: 70%; + } + } +} + +.wp-theme-twentynineteen, +.wp-theme-pubtwentynineteen { + + .jetpack-search-inline-colophon { + justify-content: flex-start; + margin: 1rem 1rem calc(3 * 1rem); + + @media only screen and (min-width: 768px) { + margin: 0 calc(10% + 60px) calc(3 * 1rem); + max-width: 80%; + } + } +} + +.wp-theme-karuna-wpcom, +.wp-theme-pubkaruna { + + .jetpack-search-inline-colophon { + justify-content: flex-start; + + @media only screen and (min-width: 768px) { + margin: 0 40% 0 0; + } + } +} + +.wp-theme-generatepress { + + .jetpack-search-inline-colophon { + display: block; + margin-top: 2rem; + clear: both; + } +} + +.wp-theme-hevor { + + .jetpack-search-inline-colophon { + justify-content: flex-start; + max-width: var(--wp--style--global--wide-size); + } +} diff --git a/projects/packages/search/src/inline-search/styles/index.scss b/projects/packages/search/src/inline-search/styles/index.scss new file mode 100644 index 0000000000000..eed1d0da2ce26 --- /dev/null +++ b/projects/packages/search/src/inline-search/styles/index.scss @@ -0,0 +1,2 @@ +@import 'corrected-query'; +@import 'colophon'; \ No newline at end of file diff --git a/projects/packages/search/tests/php/Inline_Search_Test.php b/projects/packages/search/tests/php/Inline_Search_Test.php index fd89e47854152..ff59916896ece 100644 --- a/projects/packages/search/tests/php/Inline_Search_Test.php +++ b/projects/packages/search/tests/php/Inline_Search_Test.php @@ -104,13 +104,13 @@ public static function data_provider(): array { 'post_type' => 'any', ), 'expected_api_args' => array( - 'size' => 5, - 'from' => 0, - 'fields' => array( 'post_id' ), - 'query' => 'hello_world', - 'sort' => 'score_recency', - 'langs' => array( 'en_US' ), - 'filter' => array( + 'size' => '5', + 'from' => '0', + 'fields' => array( 'post_id' ), + 'query' => 'hello_world', + 'sort' => 'score_recency', + 'langs' => array( 'en_US' ), + 'filter' => array( 'bool' => array( 'must' => array( array( @@ -121,6 +121,7 @@ public static function data_provider(): array { ), ), ), + 'highlight' => array( 'fields' => array( 'post_title', 'post_content' ) ), ), ), 'only_posts' => array( @@ -130,13 +131,13 @@ public static function data_provider(): array { 'post_type' => 'post', ), 'expected_api_args' => array( - 'size' => 5, - 'from' => 0, - 'fields' => array( 'post_id' ), - 'query' => 'only search posts', - 'sort' => 'score_recency', - 'langs' => array( 'en_US' ), - 'filter' => array( + 'size' => '5', + 'from' => '0', + 'fields' => array( 'post_id' ), + 'query' => 'only search posts', + 'sort' => 'score_recency', + 'langs' => array( 'en_US' ), + 'filter' => array( 'bool' => array( 'must' => array( array( @@ -147,6 +148,7 @@ public static function data_provider(): array { ), ), ), + 'highlight' => array( 'fields' => array( 'post_title', 'post_content' ) ), ), ), 'sort_by_date_asc' => array( @@ -158,13 +160,13 @@ public static function data_provider(): array { 'orderby' => 'date', ), 'expected_api_args' => array( - 'size' => 5, - 'from' => 0, - 'fields' => array( 'post_id' ), - 'query' => 'search by date descending', - 'sort' => 'date_asc', - 'langs' => array( 'en_US' ), - 'filter' => array( + 'size' => '5', + 'from' => '0', + 'fields' => array( 'post_id' ), + 'query' => 'search by date descending', + 'sort' => 'date_asc', + 'langs' => array( 'en_US' ), + 'filter' => array( 'bool' => array( 'must' => array( array( @@ -175,6 +177,7 @@ public static function data_provider(): array { ), ), ), + 'highlight' => array( 'fields' => array( 'post_title', 'post_content' ) ), ), ), ); diff --git a/projects/plugins/jetpack/changelog/add-inline-search-branding b/projects/plugins/jetpack/changelog/add-inline-search-branding new file mode 100644 index 0000000000000..90ef0e14a70cf --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-inline-search-branding @@ -0,0 +1,4 @@ +Significance: minor +Type: enhancement + +add-inline-search-branding diff --git a/projects/plugins/jetpack/changelog/add-inline-search-term-highlighting b/projects/plugins/jetpack/changelog/add-inline-search-term-highlighting new file mode 100644 index 0000000000000..ac65f026dc6bd --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-inline-search-term-highlighting @@ -0,0 +1,4 @@ +Significance: minor +Type: enhancement + +Add highlighting of search term in returned search results. diff --git a/projects/plugins/search/changelog/add-inline-search-branding b/projects/plugins/search/changelog/add-inline-search-branding new file mode 100644 index 0000000000000..3630b8beef243 --- /dev/null +++ b/projects/plugins/search/changelog/add-inline-search-branding @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Inline Search: add Jetpack Branding to search results. diff --git a/projects/plugins/search/changelog/add-inline-search-term-highlighting b/projects/plugins/search/changelog/add-inline-search-term-highlighting new file mode 100644 index 0000000000000..e8bd7beb03ccb --- /dev/null +++ b/projects/plugins/search/changelog/add-inline-search-term-highlighting @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Add highlighting of search term in returned search results.