Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 2.0.x
  • 8.x-1.x
  • 2.0.0
  • 2.0.0-beta1
  • 8.x-1.0
  • 8.x-1.0-alpha1
  • 8.x-1.0-alpha2
  • 8.x-1.0-alpha3
  • 8.x-1.0-alpha4
  • 8.x-1.0-beta1
  • 8.x-1.1
  • 8.x-1.2
  • 8.x-1.3
  • 8.x-1.4
  • 8.x-1.5
  • 8.x-1.6
  • 8.x-1.7
17 results

Target

Select target project
  • project/toc_api
  • issue/toc_api-3204991
  • issue/toc_api-3254404
  • issue/toc_api-3274613
  • issue/toc_api-3294155
  • issue/toc_api-3290082
  • issue/toc_api-2841748
  • issue/toc_api-3384686
  • issue/toc_api-3388382
  • issue/toc_api-3398231
  • issue/toc_api-3412644
  • issue/toc_api-3432479
  • issue/toc_api-3455312
  • issue/toc_api-3470701
  • issue/toc_api-2905420
  • issue/toc_api-3487659
  • issue/toc_api-3493738
  • issue/toc_api-2789105
  • issue/toc_api-3417862
  • issue/toc_api-3504850
  • issue/toc_api-3509064
  • issue/toc_api-3511338
  • issue/toc_api-3511348
  • issue/toc_api-3504852
  • issue/toc_api-3520197
  • issue/toc_api-3521083
  • issue/toc_api-2986763
27 results
Select Git revision
  • 2905420-fix-empty-render
  • 8.x-1.x
  • 8.x-1.0
  • 8.x-1.0-alpha1
  • 8.x-1.0-alpha2
  • 8.x-1.0-alpha3
  • 8.x-1.0-alpha4
  • 8.x-1.0-beta1
  • 8.x-1.1
  • 8.x-1.2
  • 8.x-1.3
  • 8.x-1.4
  • 8.x-1.5
13 results
Show changes
Commits on Source (5)
Showing
with 307 additions and 97 deletions
contenu
rockowitz
selectmenu
spécial
strto
tocs
include:
- project: $_GITLAB_TEMPLATES_REPO
ref: $_GITLAB_TEMPLATES_REF
file:
- '/includes/include.drupalci.main.yml'
- '/includes/include.drupalci.variables.yml'
- '/includes/include.drupalci.workflows.yml'
variables:
OPT_IN_TEST_PREVIOUS_MAJOR: 1
OPT_IN_TEST_NEXT_MINOR: 1
OPT_IN_TEST_NEXT_MAJOR: 0
RUN_JOB_UPGRADE_STATUS: 0
cspell:
allow_failure: false
phpcs:
allow_failure: false
phpstan:
allow_failure: false
phpstan (next minor):
allow_failure: true
phpstan (next major):
allow_failure: false
phpunit (previous major):
allow_failure: false
phpunit (next minor):
allow_failure: false
phpunit (next major):
allow_failure: false
upgrade status:
allow_failure: false
......@@ -14,6 +14,8 @@ options:
header_id: title
header_id_prefix: section
header_exclude_xpath: ''
wrapper: div
title_wrapper: h3
top_label: 'Back to top'
top_min: 2
top_max: 2
......
......@@ -14,6 +14,8 @@ options:
header_id: title
header_id_prefix: section
header_exclude_xpath: ''
wrapper: div
title_wrapper: h3
top_label: 'Back to top'
top_min: 2
top_max: 2
......
......@@ -14,6 +14,8 @@ options:
header_id: title
header_id_prefix: section
header_exclude_xpath: ''
wrapper: div
title_wrapper: h3
top_label: 'Back to top'
top_min: 2
top_max: 2
......
......@@ -14,6 +14,8 @@ options:
header_id: title
header_id_prefix: section
header_exclude_xpath: ''
wrapper: div
title_wrapper: h3
top_label: 'Back to top'
top_min: 2
top_max: 2
......
......@@ -14,6 +14,8 @@ options:
header_id: title
header_id_prefix: section
header_exclude_xpath: ''
wrapper: div
title_wrapper: h3
top_label: 'Back to top'
top_min: 2
top_max: 2
......
......@@ -92,3 +92,9 @@ toc_api.toc_type.*:
type: ignore
h6:
type: ignore
wrapper:
type: string
label: 'Wrapper element'
title_wrapper:
type: string
label: 'Title wrapper'
......@@ -7,7 +7,7 @@
* Add border to tree when displayed within a node
*/
.node .toc-tree {
border: 1px solid #ccc;
padding: 0 1em;
margin: 1em 0;
padding: 0 1em;
border: 1px solid #ccc;
}
......@@ -4,19 +4,15 @@
*/
(function ($, Drupal) {
"use strict";
Drupal.behaviors.tocMenu = {
attach: function (context) {
attach(context) {
$('form.toc-menu > select', context).change(function () {
var value = $(this).val();
const value = this.value;
if (value) {
location.hash = value;
window.location.hash = value;
}
this.selectedIndex = 0;
});
}
},
};
})(jQuery, Drupal);
......@@ -4,25 +4,37 @@
*/
(function ($, Drupal, once) {
"use strict";
Drupal.behaviors.tocTypeOptions = {
attach: function (context) {
$(once('.js-toc-type-options-header-min, .js-toc-type-options-header-max', context)).change(toggleHeaders);
}
};
toggleHeaders();
function toggleHeaders() {
var min = $('.js-toc-type-options-header-min').val();
var max = $('.js-toc-type-options-header-max').val();
const min = parseInt(
document.querySelector('.js-toc-type-options-header-min')?.value || 1,
10,
);
const max = parseInt(
document.querySelector('.js-toc-type-options-header-max')?.value || 6,
10,
);
for (var i = 1; i <= 6; i++) {
// Having to use the id instead of $('.js-toc-type-options-header-h' + i).
var $header = $('details[id$="-headers-h' + i + '"]');
(i >= min && i <= max) ? $header.show() : $header.hide();
for (let i = 1; i <= 6; i++) {
const $header = $(`details[id$="-headers-h${i}"]`);
if (i >= min && i <= max) {
$header.show();
} else {
$header.hide();
}
}
}
Drupal.behaviors.tocTypeOptions = {
attach(context) {
once(
'toc-type-header-change',
'.js-toc-type-options-header-min, .js-toc-type-options-header-max',
context,
).forEach((el) => {
el.addEventListener('change', toggleHeaders);
});
toggleHeaders();
},
};
})(jQuery, Drupal, once);
......@@ -2,6 +2,6 @@ name: 'TOC API example'
type: module
description: 'Example of a custom implementation of the TOC API that adds a table of contents to specified content types.'
package: 'Example modules'
core_version_requirement: ^9.4 || ^10.0
core_version_requirement: ^9.5 || ^10.2 || ^11.0
dependencies:
- toc_api:toc_api
<?php
/**
* @file
* Example of a custom implementation of the TOC API that adds a table of contents to specified content types.
* Example of a custom implementation of the TOC API.
*/
use Drupal\node\NodeInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\node\NodeInterface;
use Drupal\toc_api\Entity\TocType;
/**
* Implements hook_node_view().
*/
function toc_api_example_node_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) {
// Add TOC to 'page' and 'article' content types that are being viewed as a full (page) with a body field.
function toc_api_example_node_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, string $view_mode): void {
// Add TOC to 'page' and 'article' content types that are being viewed as a
// full (page) with a body field.
if (in_array($node->getType(), ['page', 'article']) && $view_mode == 'full' && isset($build['body'][0])) {
// Get the completely render (and filtered) body value.
$body = (string) \Drupal::service('renderer')->render($build['body'][0]);
// Get 'default' TOC type options.
/** @var \Drupal\toc_api\TocTypeInterface $toc_type */
/** @var \Drupal\toc_api\TocTypeInterface|null $toc_type */
$toc_type = TocType::load('default');
$options = ($toc_type) ? $toc_type->getOptions() : [];
......
parameters:
level: 6
ignoreErrors:
- identifier: missingType.iterableValue
......@@ -64,9 +64,9 @@ class TocType extends ConfigEntityBase implements TocTypeInterface {
/**
* The TOC type options.
*
* @var array
* @var array|null
*/
protected $options;
protected $options = NULL;
/**
* {@inheritdoc}
......
......@@ -3,15 +3,19 @@
namespace Drupal\toc_api\Plugin\Block;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultInterface;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Drupal\toc_api\TocInterface;
use Drupal\toc_api\TocManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a base TOC block which displays the current TOC module's TOC in a
* block.
* Provides a base block which displays the current TOC module's TOC in a block.
*/
abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginInterface {
......@@ -20,7 +24,21 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
protected RouteMatchInterface $routeMatch;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* The TOC manager.
*
* @var \Drupal\toc_api\TocManagerInterface
*/
protected TocManagerInterface $tocManager;
/**
* Creates a LocalActionsBlock instance.
......@@ -33,34 +51,38 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
* The plugin implementation definition.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\toc_api\TocManagerInterface $toc_manager
* The TOC manager.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) {
final public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match, EntityTypeManagerInterface $entity_type_manager, TocManagerInterface $toc_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->routeMatch = $route_match;
$this->entityTypeManager = $entity_type_manager;
$this->tocManager = $toc_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('current_route_match')
$container->get('current_route_match'),
$container->get('entity_type.manager'),
$container->get('toc_api.manager')
);
}
/**
* {@inheritdoc}
*/
public function build() {
public function build(): array {
$toc = $this->getCurrentToc();
if (empty($toc)) {
return [];
}
// Build the TOC.
$options = $toc->getOptions();
$build = [
......@@ -82,12 +104,9 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
* @return \Drupal\toc_api\TocInterface
* A TOC object.
*/
protected function getCurrentToc() {
/** @var \Drupal\toc_api\TocManagerInterface $toc_manager */
$toc_manager = \Drupal::service('toc_api.manager');
protected function getCurrentToc(): TocInterface {
// Get the new TOC instance using the module name.
return $toc_manager->getToc($this->getCurrentTocId());
return $this->tocManager->getToc($this->getCurrentTocId());
}
/**
......@@ -99,21 +118,21 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
* @return string
* The current TOC block's plugin ID.
*/
protected function getCurrentTocId() {
protected function getCurrentTocId(): string {
return $this->pluginId;
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
public function getCacheContexts(): array {
return ['route'];
}
/**
* {@inheritdoc}
*/
public function getCacheTags() {
public function getCacheTags(): array {
$node = $this->getCurrentNode();
return ($node) ? ['node:' . $node->id()] : [];
}
......@@ -122,14 +141,15 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
* Load the node associated with the current request.
*
* @return \Drupal\node\NodeInterface|null
* A node entity, or NULL if no node is not found.
* A node entity, or NULL if no node is found.
*/
protected function getCurrentNode() {
protected function getCurrentNode(): ?NodeInterface {
switch ($this->routeMatch->getRouteName()) {
// Look at the request's node revision.
case 'node.revision_show':
return node_revision_load($this->routeMatch
->getParameter('node_revision'));
$node_storage = $this->entityTypeManager->getStorage('node');
$node = $node_storage->loadRevision($this->routeMatch->getParameter('node_revision'));
return ($node instanceof NodeInterface) ? $node : NULL;
// Look at the request's node preview.
case 'entity.node.preview':
......@@ -146,14 +166,10 @@ abstract class TocBlockBase extends BlockBase implements ContainerFactoryPluginI
/**
* {@inheritdoc}
*/
protected function blockAccess(AccountInterface $account) {
$this->getCurrentTocId();
/** @var \Drupal\toc_api\TocManagerInterface $toc_manager */
$toc_manager = \Drupal::service('toc_api.manager');
protected function blockAccess(AccountInterface $account): AccessResultInterface {
// Get the new TOC instance and see if it is visible and should be
// displayed in a block.
$toc = $toc_manager->getToc($this->getCurrentTocId());
$toc = $this->tocManager->getToc($this->getCurrentTocId());
if (!$toc || !$toc->isVisible() || !$toc->isBlock()) {
return AccessResult::forbidden();
......
......@@ -72,9 +72,9 @@ class Toc implements TocInterface {
/**
* The number of root headers found in the content.
*
* @var int
* @var int|null
*/
protected $headerCount;
protected $headerCount = NULL;
/**
* The source content with unique header ids.
......@@ -100,9 +100,9 @@ class Toc implements TocInterface {
/**
* The toc represent as a tree.
*
* @var array
* @var array|null
*/
protected $tree;
protected $tree = NULL;
/**
* Existing in the source content IDs.
......@@ -192,16 +192,12 @@ class Toc implements TocInterface {
$this->allowedTags = $this->formatter()->convertAllowedTagsToArray($this->options['header_allowed_tags']);
$this->initialize();
// DEBUG:
// dsm($this->getIndex());
// dsm($this->getTree());
}
/**
* Initializes the table of content index and ensure unique header ids.
*/
protected function initialize() {
protected function initialize(): void {
$this->index = [];
// Setup an empty array of keys to track the index's keys.
......@@ -232,7 +228,7 @@ class Toc implements TocInterface {
}, array_keys($this->options['headers']));
$query = '//*[' . implode(' or ', $predicates) . ']';
// According to specification, https://www.w3.org/TR/xpath-31/#id-steps,
// "The resulting node sequence is returned in document order."
// "The resulting node sequence is returned in document order".
foreach ($xpath->query($query) as $dom_node) {
/** @var \DOMElement $dom_node */
if (in_array($dom_node, $exclude_nodes, TRUE)) {
......@@ -340,10 +336,9 @@ class Toc implements TocInterface {
'#markup' => $header_html,
'#allowed_tags' => $this->getAllowedTags(),
],
'url' => Url::fromRoute('<none>', NULL, [
'fragment' => $header_id,
]
),
'url' => Url::fromRoute('<none>', [], [
'fragment' => $header_id,
]),
];
}
......@@ -353,10 +348,11 @@ class Toc implements TocInterface {
/**
* Gets the TOC formatter.
*
* @return \Drupal\toc_api\TocFormatter.
* @return \Drupal\toc_api\TocFormatter
* The TOC formatter
*/
protected function formatter() {
// @phpstan-ignore-next-line
return \Drupal::service('toc_api.formatter');
}
......@@ -399,7 +395,8 @@ class Toc implements TocInterface {
* {@inheritdoc}
*/
public function getHeaderCount() {
if (!isset($this->headerCount)) {
if ($this->headerCount === NULL) {
$this->headerCount = 0;
foreach ($this->index as $item) {
if (empty($item['parent'])) {
$this->headerCount++;
......@@ -420,7 +417,7 @@ class Toc implements TocInterface {
* {@inheritdoc}
*/
public function getTree() {
if (!isset($this->tree)) {
if ($this->tree === NULL) {
$this->tree = [
'title' => $this->options['title'],
];
......@@ -446,7 +443,7 @@ class Toc implements TocInterface {
* @param array $children
* An array of keys to be associative to the parent header item.
*/
protected function buildTree(array &$item, array $children) {
protected function buildTree(array &$item, array $children): void {
$item['below_type'] = '';
$item['below'] = [];
foreach ($children as $key) {
......@@ -499,8 +496,6 @@ class Toc implements TocInterface {
*
* @param \DOMDocument $dom
* DOM object.
*
* @return void
*/
protected function collectExistingIds(\DOMDocument $dom): void {
$xpath = new \DOMXPath($dom);
......@@ -519,7 +514,6 @@ class Toc implements TocInterface {
*
* @param \DOMDocument $dom
* DOM object.
* @return void
*/
protected function useIdsOnly(\DOMDocument $dom): void {
$xpath = new \DOMXPath($dom);
......
......@@ -4,11 +4,14 @@ namespace Drupal\toc_api;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Render\Markup;
use Drupal\Core\Render\RendererInterface;
/**
* Defines a service that builds and renders a table of contents and update an
* HTML document's headers.
* Defines a service to build TOC.
*
* This service builds and renders a table of contents and update an HTML
* document's headers.
*/
class TocBuilder implements TocBuilderInterface {
......@@ -95,14 +98,14 @@ class TocBuilder implements TocBuilderInterface {
$fragment_body = $fragment_dom->getElementsByTagName('body')->item(0);
// Import the new (header) nodes onto the original DOMDocument.
foreach ($fragment_body->childNodes as $fragment_child_node) {
$fragment_child_node = $dom->importNode($fragment_child_node, true);
$fragment_child_node = $dom->importNode($fragment_child_node, TRUE);
$fragment_node->appendChild($fragment_child_node);
}
// Replace the header node.
$replace = TRUE;
if (!empty($h_nodes)) {
// Make sure we are not going
// Make sure we are not going.
foreach ($h_nodes as $h) {
if ($dom_node->parentNode->isSameNode($h)) {
$replace = FALSE;
......@@ -133,7 +136,7 @@ class TocBuilder implements TocBuilderInterface {
$fragment_body = $fragment_dom->getElementsByTagName('body')->item(0);
// Import the new (header) nodes onto the original DOMDocument.
foreach ($fragment_body->childNodes as $fragment_child_node) {
$fragment_child_node = $dom->importNode($fragment_child_node, true);
$fragment_child_node = $dom->importNode($fragment_child_node, TRUE);
$fragment_node->appendChild($fragment_child_node);
}
......@@ -150,10 +153,13 @@ class TocBuilder implements TocBuilderInterface {
*/
public function renderToc(TocInterface $toc) {
if (!$toc->isVisible()) {
return '';
return Markup::create('');
}
$build = $this->buildToc($toc);
if (empty($build)) {
return Markup::create('');
}
return $this->renderer->render($build);
}
......
......@@ -26,8 +26,8 @@ interface TocBuilderInterface {
* A TOC object.
*
* @return array
* A render array containing the table of content's body content with bookmarked, typed, and custom
* headers with back to top links.
* A render array containing the table of content's body content with
* bookmarked, typed, and custom headers with back to top links.
*/
public function buildContent(TocInterface $toc);
......
......@@ -3,7 +3,7 @@
namespace Drupal\toc_api;
/**
* Defines a service for formatting a table of content's headers, numbering, and ids..
* Defines a service for formatting a TOC headers, numbering, and ids.
*/
class TocFormatter implements TocFormatterInterface {
......@@ -12,7 +12,90 @@ class TocFormatter implements TocFormatterInterface {
*/
public function convertStringToId($text) {
// Replace accents with their counterparts.
$text = strtr($text, ['Š' => 'S', 'š' => 's', 'Đ' => 'Dj', 'đ' => 'dj', 'Ž' => 'Z', 'ž' => 'z', 'Č' => 'C', 'č' => 'c', 'Ć' => 'C', 'ć' => 'c', 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'A', 'Ç' => 'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ý' => 'Y', 'Þ' => 'B', 'ß' => 'Ss', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a', 'æ' => 'a', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'o', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ý' => 'y', 'þ' => 'b', 'ÿ' => 'y', 'Ŕ' => 'R', 'ŕ' => 'r', 'Ā' => 'A', 'Ē' => 'E', 'Ī' => 'I', 'Ō' => 'O', 'Ū' => 'U', 'ā' => 'a', 'ē' => 'e', 'ī' => 'i', 'ō' => 'o', 'ū' => 'u']);
$text = strtr($text, [
'Š' => 'S',
'š' => 's',
'Đ' => 'Dj',
'đ' => 'dj',
'Ž' => 'Z',
'ž' => 'z',
'Č' => 'C',
'č' => 'c',
'Ć' => 'C',
'ć' => 'c',
'À' => 'A',
'Á' => 'A',
'Â' => 'A',
'Ã' => 'A',
'Ä' => 'A',
'Å' => 'A',
'Æ' => 'A',
'Ç' => 'C',
'È' => 'E',
'É' => 'E',
'Ê' => 'E',
'Ë' => 'E',
'Ì' => 'I',
'Í' => 'I',
'Î' => 'I',
'Ï' => 'I',
'Ñ' => 'N',
'Ò' => 'O',
'Ó' => 'O',
'Ô' => 'O',
'Õ' => 'O',
'Ö' => 'O',
'Ø' => 'O',
'Ù' => 'U',
'Ú' => 'U',
'Û' => 'U',
'Ü' => 'U',
'Ý' => 'Y',
'Þ' => 'B',
'ß' => 'Ss',
'à' => 'a',
'á' => 'a',
'â' => 'a',
'ã' => 'a',
'ä' => 'a',
'å' => 'a',
'æ' => 'a',
'ç' => 'c',
'è' => 'e',
'é' => 'e',
'ê' => 'e',
'ë' => 'e',
'ì' => 'i',
'í' => 'i',
'î' => 'i',
'ï' => 'i',
'ð' => 'o',
'ñ' => 'n',
'ò' => 'o',
'ó' => 'o',
'ô' => 'o',
'õ' => 'o',
'ö' => 'o',
'ø' => 'o',
'ù' => 'u',
'ú' => 'u',
'û' => 'u',
'ý' => 'y',
'þ' => 'b',
'ÿ' => 'y',
'Ŕ' => 'R',
'ŕ' => 'r',
'Ā' => 'A',
'Ē' => 'E',
'Ī' => 'I',
'Ō' => 'O',
'Ū' => 'U',
'ā' => 'a',
'ē' => 'e',
'ī' => 'i',
'ō' => 'o',
'ū' => 'u',
]);
// Lowercase.
$text = strtolower($text);
......@@ -40,9 +123,13 @@ class TocFormatter implements TocFormatterInterface {
* {@inheritdoc}
*/
public function convertNumberToListTypeValue($number, $type) {
if ($type === NULL) {
$type = '';
}
$case_func = NULL;
// Check if type should upper or lower cased.
if (preg_match('/^(upper|lower)-(.+)$/', $type, $match)) {
if (preg_match('/^(upper|lower)-(.+)$/', (string) $type, $match)) {
$type = $match[2];
$case_func = 'strto' . $match[1];
}
......@@ -72,7 +159,21 @@ class TocFormatter implements TocFormatterInterface {
* {@inheritdoc}
*/
public function convertNumberToRomanNumeral($number) {
$roman_numerals = ['M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1];
$roman_numerals = [
'M' => 1000,
'CM' => 900,
'D' => 500,
'CD' => 400,
'C' => 100,
'XC' => 90,
'L' => 50,
'XL' => 40,
'X' => 10,
'IX' => 9,
'V' => 5,
'IV' => 4,
'I' => 1,
];
$result = '';
foreach ($roman_numerals as $roman_numeral => $roman_number) {
$matches = intval($number / $roman_number);
......@@ -86,7 +187,34 @@ class TocFormatter implements TocFormatterInterface {
* {@inheritdoc}
*/
public function convertNumberToLetter($number) {
static $letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
static $letters = [
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
];
return $letters[(($number - 1) % 26)];
}
......