diff --git a/core/modules/help/src/HelpSearchInterface.php b/core/modules/help/src/HelpSearchInterface.php
new file mode 100644
index 0000000000..f1a31361dc
--- /dev/null
+++ b/core/modules/help/src/HelpSearchInterface.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Drupal\help;
+
+use Drupal\Core\Language\LanguageInterface;
+
+/**
+ * Provides an interface for a HelpSection plugin that also supports search.
+ *
+ * @see \Drupal\help\HelpSectionPluginInterface
+ */
+interface HelpSearchInterface {
+
+  /**
+   * Returns the IDs of topics that should be indexed for searching.
+   *
+   * @return string[]
+   *   An array of topic IDs that should be searchable. IDs need to be
+   *   unique within this HelpSection plugin type.
+   */
+  public function listSearchableTopics();
+
+  /**
+   * Renders one topic for search indexing.
+   *
+   * @param string $id
+   *   The ID of the topic to be indexed.
+   * @param \Drupal\Core\LanguageInterface $language
+   *   The language to render the topic in.
+   *
+   * @return array
+   *   A render array containing the help text to index. It should include
+   *   the title of the item in an H1 tag.
+   */
+  public function renderTopicForSearch($id, LanguageInterface $language);
+
+  /**
+   * Prepares one topic for search results.
+   *
+   * @param string $id
+   *   The ID of the topic to be shown in search results.
+   * @param \Drupal\Core\LanguageInterface $language
+   *   The language to show the topic in.
+   * @param string $keys
+   *   Keywords that were searched for.
+   *
+   * @return array
+   *   An array of information for search results, containing the following
+   *   elements:
+   *   - link: URL of the topic.
+   *   - title: Title of the topic.
+   *   - snippet: Excerpt of the topic (use search_excerpt() function).
+   *   - langcode: Language code.
+   */
+  public function prepareSearchResult($id, LanguageInterface $language, $keys);
+
+}
diff --git a/core/modules/help/src/HelpSectionPluginInterface.php b/core/modules/help/src/HelpSectionPluginInterface.php
index cf377c4202..52e07bb05c 100644
--- a/core/modules/help/src/HelpSectionPluginInterface.php
+++ b/core/modules/help/src/HelpSectionPluginInterface.php
@@ -14,6 +14,9 @@
  * \Drupal\help\HelpSectionManager plugin manager class. There is a base
  * class that may be helpful:
  * \Drupal\help\Plugin\HelpSection\HelpSectionPluginBase.
+ *
+ * In addition, plugins of this type that want to support searching (using the
+ * help_search module) should also implement \Drupal\help\HelpSearchInterface.
  */
 interface HelpSectionPluginInterface extends PluginInspectionInterface, CacheableDependencyInterface {
 
diff --git a/core/modules/help_search/config/install/search.page.help_search.yml b/core/modules/help_search/config/install/search.page.help_search.yml
new file mode 100644
index 0000000000..b09d96ad77
--- /dev/null
+++ b/core/modules/help_search/config/install/search.page.help_search.yml
@@ -0,0 +1,11 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - help_search
+id: help_search
+label: Help
+path: help
+weight: 0
+plugin: help_search
+configuration: {  }
diff --git a/core/modules/help_search/help_search.info.yml b/core/modules/help_search/help_search.info.yml
new file mode 100644
index 0000000000..9c44f73fd5
--- /dev/null
+++ b/core/modules/help_search/help_search.info.yml
@@ -0,0 +1,9 @@
+name: Help Search
+type: module
+description: 'Provides searching for help'
+core: 8.x
+package: Core (Experimental)
+version: VERSION
+dependencies:
+  - drupal:help
+  - drupal:search
diff --git a/core/modules/help_search/help_search.install b/core/modules/help_search/help_search.install
new file mode 100644
index 0000000000..c858cdbf37
--- /dev/null
+++ b/core/modules/help_search/help_search.install
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the help_search module.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function help_search_schema() {
+  $schema['help_search_items'] = [
+    'description' => 'Stores information about indexed help search items',
+    'fields' => [
+      'sid' => [
+        'description' => 'Numeric index of this item in the search index',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ],
+      'plugin_type' => [
+        'description' => 'The help plugin type the item comes from',
+        'type' => 'varchar_ascii',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ],
+      'permission' => [
+        'description' => 'The permission needed to view this item',
+        'type' => 'varchar_ascii',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ],
+      'id' => [
+        'description' => 'The plugin ID of the item',
+        'type' => 'varchar_ascii',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ],
+    ],
+    'primary key' => ['sid'],
+    'indexes' => [
+      'plugin_type' => ['plugin_type'],
+      'id' => ['id'],
+    ],
+  ];
+
+  return $schema;
+}
diff --git a/core/modules/help_search/help_search.module b/core/modules/help_search/help_search.module
new file mode 100644
index 0000000000..5a96a8f44e
--- /dev/null
+++ b/core/modules/help_search/help_search.module
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Provides searching for help.
+ */
+
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Url;
+
+/**
+ * Implements hook_help().
+ */
+function help_search_help($route_name, RouteMatchInterface $route_match) {
+  switch ($route_name) {
+    case 'help.page.help_search':
+      $search_help = Url::fromRoute('help.page', ['name' => 'search'])->toString();
+      $output = '';
+      $output .= '<h3>' . t('About') . '</h3>';
+      $output .= '<p>' . t('The Help Search module adds search capability for types of help that support searching. For more information, see the <a href=":online">online documentation for the Help Search module</a>.', [':online' => 'https://www.drupal.org/modules/help_search']) . '</p>';
+      $output .= '<h3>' . t('Uses') . '</h3>';
+      $output .= '<dl>';
+      $output .= '<dt>' . t('Configuring help search') . '</dt>';
+      $output .= '<dd>' . t('To search help, you will need to configure a search page (one is set up by default), and add a search block to the Help page or another administrative page. Then users with search permissions, and permission to view help, will be able to search help. See the <a href=":search_help">Search module help page</a> for more information.', [':search_help' => $search_help]) . '</dd>';
+      $output .= '</dl>';
+      return ['#markup' => $output];
+  }
+}
+
+/**
+ * Implements hook_rebuild().
+ */
+function help_search_rebuild() {
+  // We need to trigger a reindex when a module or theme is installed,
+  // uninstalled, or updated; and when languages are added, translations are
+  // changed, or string overrides are changed. These situations can cause an
+  // indexed help item to have different text, or for help items to be added
+  // or removed. So, we use a state variable to keep track of the need to
+  // reindex.
+  Drupal::state()->set('help_search_reindex_needed', TRUE);
+}
diff --git a/core/modules/help_search/src/Plugin/Search/HelpSearch.php b/core/modules/help_search/src/Plugin/Search/HelpSearch.php
new file mode 100644
index 0000000000..8982408353
--- /dev/null
+++ b/core/modules/help_search/src/Plugin/Search/HelpSearch.php
@@ -0,0 +1,440 @@
+<?php
+
+namespace Drupal\help_search\Plugin\Search;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Config\Config;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\Core\Messenger\MessengerInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Access\AccessibleInterface;
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\Core\State\StateInterface;
+use Drupal\help\HelpSectionManager;
+use Drupal\help\HelpSectionPluginInterface;
+use Drupal\help\HelpSearchInterface;
+use Drupal\search\Plugin\SearchPluginBase;
+use Drupal\search\Plugin\SearchIndexingInterface;
+use Drupal\Search\SearchQuery;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Handles searching for help using the Search module index.
+ *
+ * Help items are indexed if their HelpSection plugin implements
+ * \Drupal\help\HelpSearchInterface.
+ *
+ * @see \Drupal\help\HelpSearchInterface
+ * @see \Drupal\help\HelpSectionPluginInterface
+ *
+ * @SearchPlugin(
+ *   id = "help_search",
+ *   title = @Translation("Help")
+ * )
+ */
+class HelpSearch extends SearchPluginBase implements AccessibleInterface, SearchIndexingInterface {
+
+  /**
+   * The current database connection.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $database;
+
+  /**
+   * A config object for 'search.settings'.
+   *
+   * @var \Drupal\Core\Config\Config
+   */
+  protected $searchSettings;
+
+  /**
+   * The language manager.
+   *
+   * @var \Drupal\Core\Language\LanguageManagerInterface
+   */
+  protected $languageManager;
+
+  /**
+   * The Drupal account to use for checking for access to advanced search.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $account;
+
+  /**
+   * The Renderer service to format the username and node.
+   *
+   * @var \Drupal\Core\Render\RendererInterface
+   */
+  protected $renderer;
+
+  /**
+   * The messenger.
+   *
+   * @var \Drupal\Core\Messenger\MessengerInterface
+   */
+  protected $messenger;
+
+  /**
+   * The state object.
+   *
+   * @var \Drupal\Core\State\StateInterface
+   */
+  protected $state;
+
+  /**
+   * The help section plugin manager.
+   *
+   * @var \Drupal\help\HelpSectionManager
+   */
+  protected $helpManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('database'),
+      $container->get('config.factory')->get('search.settings'),
+      $container->get('language_manager'),
+      $container->get('renderer'),
+      $container->get('messenger'),
+      $container->get('current_user'),
+      $container->get('state'),
+      $container->get('plugin.manager.help_section')
+    );
+  }
+
+  /**
+   * Constructs a \Drupal\help_search\Plugin\Search\HelpSearch object.
+   *
+   * @param array $configuration
+   *   Configuration for the plugin.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Database\Connection $database
+   *   The current database connection.
+   * @param \Drupal\Core\Config\Config $search_settings
+   *   A config object for 'search.settings'.
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   *   The language manager.
+   * @param \Drupal\Core\Render\RendererInterface $renderer
+   *   The renderer.
+   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
+   *   The messenger.
+   * @param \Drupal\Core\Session\AccountInterface $account
+   *   The $account object to use for checking for access to view help.
+   * @param \Drupal\Core\State\StateInterface $state
+   *   The state object.
+   * @param \Drupal\help\HelpSectionManager $help_manager
+   *   The help section manager.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, Config $search_settings, LanguageManagerInterface $language_manager, RendererInterface $renderer, MessengerInterface $messenger, AccountInterface $account = NULL, StateInterface $state, HelpSectionManager $help_manager) {
+    $this->database = $database;
+    $this->searchSettings = $search_settings;
+    $this->languageManager = $language_manager;
+    $this->renderer = $renderer;
+    $this->messenger = $messenger;
+    $this->account = $account;
+    $this->state = $state;
+    $this->helpManager = $help_manager;
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    // @todo cache tags?
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access($operation = 'view', AccountInterface $account = NULL, $return_as_object = FALSE) {
+    $result = AccessResult::allowedIfHasPermission($account, 'access administration pages');
+    return $return_as_object ? $result : $result->isAllowed();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getType() {
+    return $this->getPluginId();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute() {
+    if ($this->isSearchExecutable()) {
+      $results = $this->findResults();
+
+      if ($results) {
+        return $this->prepareResults($results);
+      }
+    }
+
+    return [];
+  }
+
+  /**
+   * Finds the search results.
+   *
+   * @return array
+   *   Array of items of help that contains the keywords and the current user
+   *   has access to view. Each item is an array with the following elements:
+   *   - sid: (int) Search ID of the item.
+   *   - langcode: (string) Language code of the item.
+   */
+  protected function findResults() {
+    // @todo
+    // Note: check access! User needs to have the permission shown in the
+    // permission column of the help_search_items table for the given item,
+    // in order to view that type of help (or see it in search results).
+    return [];
+  }
+
+  /**
+   * Prepares search results for display.
+   *
+   * @param array $items
+   *   List of help items to prepare (output of self::findResults()).
+   *
+   * @return array
+   *   List of search result arrays, with links, snippets, etc.
+   */
+  protected function prepareResults(array $items) {
+    $results = [];
+    $plugins = [];
+    $keys = $this->getKeywords();
+    foreach ($items as $item) {
+      $result = $this->database->select('help_search_items', 'hsi')
+        ->condition('sid', $item->sid)
+        ->fields('hsi', ['plugin_type', 'id'])
+        ->execute();
+      foreach ($result as $record) {
+        $type = $record->plugin_type;
+        if (!isset($plugins[$type])) {
+          $plugins[$type] = $this->getSectionPlugin($type);
+        }
+        if ($plugins[$type]) {
+          $results[] = $plugins[$type]->prepareSearchResult($record->id, $item->langcode, $keys);
+        }
+      }
+    }
+
+    return $results;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function updateIndex() {
+    // See if we need to update the list of items to be indexed.
+    if ($this->state->get('help_search_reindex_needed', TRUE)) {
+      $this->markForReindex();
+    }
+
+    // Find some items that need to be updated. Start with ones that have
+    // never been indexed, and if there is still space in the limit, add in
+    // ones that are marked to reindex.
+    $limit = (int) $this->searchSettings->get('index.cron_limit');
+
+    $query = $this->database->select('help_search_items', 'hsi');
+    $query->fields('hsi', ['sid', 'plugin_type', 'id']);
+    $query->leftJoin('search_dataset', 'sd', 'sd.sid = hsi.sid AND sd.type = :type', [':type' => $this->getPluginId()]);
+    $query->where('sd.sid IS NULL');
+    $query->groupBy('hsi.sid')
+      ->range(0, $limit);
+    $items = $query->execute()->fetchAll();
+
+    if (count($items) < $limit) {
+      $query = $this->database->select('help_search_items', 'hsi');
+      $query->fields('hsi', ['sid', 'plugin_type', 'id']);
+      $query->leftJoin('search_dataset', 'sd', 'sd.sid = hsi.sid AND sd.type = :type', [':type' => $this->getPluginId()]);
+      $query->condition('sd.reindex', 0, '<>');
+      $query->groupBy('hsi.sid')
+        ->range(0, $limit - count($items));
+      $items = $items + $query->execute()->fetchAll();
+    }
+
+    // Index items, in all available languages.
+    $language_list = $this->languageManager->getLanguages(LanguageInterface::STATE_CONFIGURABLE);
+    $plugins = [];
+
+    foreach ($items as $item) {
+      $type = $item->plugin_type;
+      if (!isset($plugins[$type])) {
+        $plugins[$type] = $this->getSectionPlugin($type);
+      }
+
+      if (!$plugins[$type]) {
+        $this->removeItemsFromIndex($item->sid);
+        continue;
+      }
+
+      $plugin = $plugins[$type];
+      search_index_clear($this->getPluginId(), $item->sid);
+      foreach ($language_list as $langcode => $language) {
+        $build = $plugin->renderTopicForSearch($item->id, $language);
+        $text = $this->renderer->renderPlain($build);
+        search_index($this->getPluginId(), $item->sid, $langcode, $text);
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function indexClear() {
+    search_index_clear($this->getPluginId());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function markForReindex() {
+    // Update the list of help items. Start by fetching the existing list,
+    // so we can remove items not found at the end.
+    $old_list = $this->database->select('help_search_items', 'hsi')
+      ->fields('hsi', ['sid', 'id', 'plugin_type', 'permission'])
+      ->execute()
+      ->fetchAll();
+    $old_list_ordered = [];
+    $max_sid = 0;
+    $sids_to_remove = [];
+    foreach ($old_list as $item) {
+      $old_list_ordered[$item->plugin_type][$item->id] = $item;
+      if ($item->sid > $max_sid) {
+        $max_sid = $item->sid;
+      }
+      $sids_to_remove[$item->sid] = $item->sid;
+    }
+
+    $plugins = $this->helpManager->getDefinitions();
+    foreach ($plugins as $plugin_id => $plugin_definition) {
+      /** @var \Drupal\help\HelpSectionPluginInterface $plugin */
+      $plugin = $this->getSectionPlugin($plugin_id);
+      if (!$plugin) {
+        continue;
+      }
+      $permission = (isset ($plugin_definition['permission']) ? $plugin_definition['permission'] : '');
+      $items = $plugin->listSearchableTopics();
+      if (!count($items)) {
+        continue;
+      }
+      foreach ($items as $id) {
+        if (isset($old_list_ordered[$plugin_id][$id])) {
+          $old_item = $old_list_ordered[$plugin_id][$id];
+          if ($old_item->permission == $permission) {
+            // Record has not changed.
+            unset($sids_to_remove[$old_item->sid]);
+          }
+          else {
+            // Permission has changed, update record.
+            $this->database->update('help_search_items')
+              ->condition('sid', $old_item->sid)
+              ->fields(['permission' => $permission])
+              ->execute();
+          }
+        }
+        else {
+          // New record, create it.
+          $this->database->insert('help_search_items')
+            ->fields([
+              'sid' => $max_sid + 1,
+              'plugin_type' => $plugin_id,
+              'permission' => $permission,
+              'id' => $id,
+            ])
+            ->execute();
+          $max_sid++;
+        }
+      }
+    }
+
+    // Remove remaining items from the index.
+    $this->removeItemsFromIndex($sids_to_remove);
+
+    // Mark all items currently in the search index database as needing
+    // reindex.
+    search_mark_for_reindex($this->getPluginId());
+    $this->state->set('help_search_reindex_needed', FALSE);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function indexStatus() {
+    if ($this->state->get('help_search_reindex_needed', TRUE)) {
+      $this->markForReindex();
+    }
+
+    $total = $this->database->select('help_search_items', 'hsi')
+      ->countQuery()
+      ->execute()
+      ->fetchField();
+
+    $query = $this->database->select('help_search_items', 'hsi');
+    $query->addExpression('COUNT(DISTINCT(hsi.sid))');
+    $query->leftJoin('search_dataset', 'sd', 'hsi.sid = sd.sid AND sd.type = :type', [':type' => $this->getPluginId()]);
+    $condition = new Condition('OR');
+    $condition->condition('sd.reindex', 0, '<>')
+      ->isNull('sd.sid');
+    $query->condition($condition);
+    $remaining = $query->execute()->fetchField();
+
+    return [
+      'remaining' => $remaining,
+      'total' => $total,
+    ];
+  }
+
+  /**
+   * Removes an item or items from the search index.
+   *
+   * @param int|int[] $sids
+   *   Search ID (sid) of item or items to remove.
+   */
+  protected function removeItemsFromIndex($sids) {
+    if (!is_array($sids)) {
+      $sids = [$sids];
+    }
+
+    // Remove items in batches of 100.
+    for ($start = 0; $start < count($sids); $start += 100) {
+      $this_list = array_slice($sids, $start, 100);
+      $this->database->delete('help_search_items')
+        ->condition('sid', $this_list, 'IN')
+        ->execute();
+      search_index_clear($this->getPluginId(), $this_list);
+    }
+  }
+
+  /**
+   * Instantiates a help section plugin and verifies it is searchable.
+   *
+   * @param string $plugin_type
+   *   Type of plugin to instantiate.
+   *
+   * @return \Drupal\help\HelpSectionPluginInterface|false
+   *   Plugin object, or FALSE if it is not a searchable type.
+   */
+  protected function getSectionPlugin($plugin_type) {
+    /** @var \Drupal\help\HelpSectionPluginInterface $plugin */
+    $plugin = $this->helpManager->createInstance($plugin_type);
+    if ($plugin &&
+      $plugin instanceof HelpSectionPluginInterface &&
+      $plugin instanceof HelpSearchInterface ) {
+      return $plugin;
+    }
+
+    return FALSE;
+  }
+
+}
diff --git a/core/modules/help_topics/src/Plugin/HelpSection/HelpTopicSection.php b/core/modules/help_topics/src/Plugin/HelpSection/HelpTopicSection.php
index 62d30631b1..23fef2ca48 100644
--- a/core/modules/help_topics/src/Plugin/HelpSection/HelpTopicSection.php
+++ b/core/modules/help_topics/src/Plugin/HelpSection/HelpTopicSection.php
@@ -3,8 +3,10 @@
 namespace Drupal\help_topics\Plugin\HelpSection;
 
 use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\help\HelpSearchInterface;
 use Drupal\help_topics\HelpTopicPluginInterface;
 use Drupal\help_topics\HelpTopicPluginManagerInterface;
+use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\help\Plugin\HelpSection\HelpSectionPluginBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -24,7 +26,7 @@
  *   experimental modules and development releases of contributed modules.
  *   See https://www.drupal.org/core/experimental for more information.
  */
-class HelpTopicSection extends HelpSectionPluginBase implements ContainerFactoryPluginInterface {
+class HelpTopicSection extends HelpSectionPluginBase implements ContainerFactoryPluginInterface, HelpSearchInterface {
 
   /**
    * The plugin manager.
@@ -136,6 +138,62 @@ protected function getPlugins() {
     return $this->topLevelPlugins;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function listSearchableTopics() {
+    $definitions = $this->pluginManager->getDefinitions();
+    $ids = [];
+    foreach ($definitions as $definition) {
+      $ids[] = $definition['id'];
+    }
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function renderTopicForSearch($id, LanguageInterface $language) {
+    $plugin = $this->pluginManager->createInstance($id);
+    if (!$plugin) {
+      return [];
+    }
+
+    $langcode = $language->getId();
+    // @todo Figure out how to set the language, so that title and body
+    // get translated.
+    $title = $plugin->getLabel();
+    $body = $plugin->getBody();
+    return [
+      'body' => $body,
+      'title' => [
+        '#type' => '#markup',
+        '#markup' => '<h1>' . $title . '</h1>',
+      ],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareSearchResult($id, LanguageInterface $language, $keys) {
+    $langcode = $language->getId();
+    $plugin = $this->pluginManager->createInstance($id);
+    if (!$plugin) {
+      return [];
+    }
+
+    // @todo Figure out how to set the language, so that title and body
+    // get translated.
+    $text = $plugin->getBody();
+    return [
+      'link' => $plugin->toUrl(),
+      'title' => $plugin->getLabel(),
+      'snippet' => search_excerpt($keys, $text, $langcode),
+      'langcode' => $langcode,
+    ];
+  }
+
   /**
    * Gets the merged CacheableMetadata for all the top level help topic plugins.
    *
