diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 769e34c..665ca73 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -568,9 +568,8 @@ function template_preprocess_datetime_wrapper(&$variables) {
*
* @param array $variables
* An associative array containing:
- * - links: An associative array of links to be themed. The key for each link
- * is used as its CSS class. Each link should be itself an array, with the
- * following elements:
+ * - links: An array of links to be themed. Each link should be itself an
+ * array, with the following elements:
* - title: The link text.
* - url: (optional) The url object to link to. If omitted, no a tag is
* printed out.
diff --git a/core/modules/system/src/Tests/Theme/FunctionsTest.php b/core/modules/system/src/Tests/Theme/FunctionsTest.php
index 5e31422..e64f10e 100644
--- a/core/modules/system/src/Tests/Theme/FunctionsTest.php
+++ b/core/modules/system/src/Tests/Theme/FunctionsTest.php
@@ -290,6 +290,127 @@ function testLinks() {
}
/**
+ * Tests links.html.twig.
+ */
+ function testIndexedKeyedLinks() {
+ // Turn off the query for the
+ // \Drupal\Core\Utility\LinkGeneratorInterface::generate() method to compare
+ // the active link correctly.
+ $original_query = \Drupal::request()->query->all();
+ \Drupal::request()->query->replace([]);
+ // Verify that empty variables produce no output.
+ $variables = [];
+ $expected = '';
+ $this->assertThemeOutput('links', $variables, $expected, 'Empty %callback generates no output.');
+
+ $variables = [];
+ $variables['heading'] = 'Some title';
+ $expected = '';
+ $this->assertThemeOutput('links', $variables, $expected, 'Empty %callback with heading generates no output.');
+
+ // Verify that a list of links is properly rendered.
+ $variables = [];
+ $variables['attributes'] = ['id' => 'somelinks'];
+ $variables['links'] = array(
+ array(
+ 'title' => 'A ',
+ 'url' => Url::fromUri('base:a/link'),
+ ),
+ array(
+ 'title' => 'Plain "text"',
+ ),
+ array(
+ 'title' => SafeMarkup::format('@text', array('@text' => 'potentially unsafe text that be escaped')),
+ ),
+ array(
+ 'title' => 'Front page',
+ 'url' => Url::fromRoute(''),
+ ),
+ array(
+ 'title' => 'Test route',
+ 'url' => Url::fromRoute('router_test.1'),
+ ),
+ array(
+ 'title' => 'Query test route',
+ 'url' => Url::fromRoute('router_test.1'),
+ 'query' => array(
+ 'key' => 'value',
+ )
+ ),
+ );
+
+ $expected_links = '';
+ $expected_links .= '
';
+ $expected = $expected_heading . $expected_links;
+ $this->assertThemeOutput('links', $variables, $expected);
+ }
+
+ /**
* Test the use of drupal_pre_render_links() on a nested array of links.
*/
function testDrupalPreRenderLinks() {
diff --git a/core/modules/system/templates/links.html.twig b/core/modules/system/templates/links.html.twig
index 86713b5..77e7260 100644
--- a/core/modules/system/templates/links.html.twig
+++ b/core/modules/system/templates/links.html.twig
@@ -13,7 +13,6 @@
* to l() as its $options parameter.
* - attributes: (optional) HTML attributes for the anchor, or for the
* tag if no 'href' is supplied.
- * - link_key: The link CSS class.
* - heading: (optional) A heading to precede the links.
* - text: The heading text.
* - level: The heading level (e.g. 'h2', 'h3').
@@ -43,8 +42,8 @@
{%- endif -%}
{%- endif -%}
- {%- for key, item in links -%}
-
+ {%- for item in links -%}
+
{%- if item.link -%}
{{ item.link }}
{%- elseif item.text_attributes -%}
diff --git a/core/themes/classy/templates/content/links--node.html.twig b/core/themes/classy/templates/content/links--node.html.twig
index f4c3d72..a7b91e7 100644
--- a/core/themes/classy/templates/content/links--node.html.twig
+++ b/core/themes/classy/templates/content/links--node.html.twig
@@ -13,7 +13,6 @@
* to l() as its $options parameter.
* - attributes: (optional) HTML attributes for the anchor, or for the
* tag if no 'href' is supplied.
- * - link_key: The link CSS class.
* - heading: (optional) A heading to precede the links.
* - text: The heading text.
* - level: The heading level (e.g. 'h2', 'h3').
diff --git a/core/themes/classy/templates/navigation/links.html.twig b/core/themes/classy/templates/navigation/links.html.twig
index f82f41a..c1bff6b 100644
--- a/core/themes/classy/templates/navigation/links.html.twig
+++ b/core/themes/classy/templates/navigation/links.html.twig
@@ -13,7 +13,6 @@
* to l() as its $options parameter.
* - attributes: (optional) HTML attributes for the anchor, or for the
* tag if no 'href' is supplied.
- * - link_key: The link CSS class.
* - heading: (optional) A heading to precede the links.
* - text: The heading text.
* - level: The heading level (e.g. 'h2', 'h3').
@@ -41,8 +40,8 @@
{%- endif -%}
{%- endif -%}
- {%- for key, item in links -%}
-
+ {%- for item in links -%}
+
{%- if item.link -%}
{{ item.link }}
{%- elseif item.text_attributes -%}
diff --git a/core/themes/stable/stable.theme b/core/themes/stable/stable.theme
new file mode 100644
index 0000000..663667a
--- /dev/null
+++ b/core/themes/stable/stable.theme
@@ -0,0 +1,20 @@
+ $value) {
+ if (!is_numeric($key)) {
+ $class = Html::getClass($key);
+ $variables['links'][$key]['attributes']->addClass($class);
+ }
+ }
+ }
+}
diff --git a/core/themes/stable/templates/navigation/links.html.twig b/core/themes/stable/templates/navigation/links.html.twig
index f82f41a..c1bff6b 100644
--- a/core/themes/stable/templates/navigation/links.html.twig
+++ b/core/themes/stable/templates/navigation/links.html.twig
@@ -13,7 +13,6 @@
* to l() as its $options parameter.
* - attributes: (optional) HTML attributes for the anchor, or for the
* tag if no 'href' is supplied.
- * - link_key: The link CSS class.
* - heading: (optional) A heading to precede the links.
* - text: The heading text.
* - level: The heading level (e.g. 'h2', 'h3').
@@ -41,8 +40,8 @@
{%- endif -%}
{%- endif -%}