Skip to content

Commit

Permalink
Merge branch 'release/3.2.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
rhukster committed May 6, 2024
2 parents 4818734 + a3f08ee commit db406a9
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 15 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# v3.2.3
## 05/06/2024

1. [](#new)
* Added french translation [#28](https://github.com/trilbymedia/grav-plugin-page-toc/pulls/28)
* Added option to whitelist HTML tags in TOC [#36](https://github.com/trilbymedia/grav-plugin-page-toc/pulls/36)
* Added option to set user templates in which anchors are generated [#37](https://github.com/trilbymedia/grav-plugin-page-toc/pulls/37)
1. [](#bugfix)
* Revert Twig macro to use `_self` as it was breaking the recursion. Deprecated message remains but can't be helped. [#38](https://github.com/trilbymedia/grav-plugin-page-toc/issues/38)

# v3.2.2
## 05/10/2023

Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Here is the default configuration and an explanation of available options:
enabled: true # Plugin enabled
include_css: true # Include CSS
active: true # Anchor IDs processed and generated for all pages
templates: # Templates for which anchors should be generated if default is disabled
start: 1 # Start header tag level (1 = h1) for TOC
depth: 6 # Depth from start (2 = 2 levels deep) for TOC
hclass: # Custom Header TOC styling classes
Expand All @@ -61,6 +62,8 @@ page-toc:
active: true
```

Alternatively, you can activate anchor generation on all pages using a given set of `templates`.

You can also configure which header tags to start and depth on when building the id attribute anchors by changing the `start` and `depth` values. This can also be done on a per-page basis.

For example if you had a start of `3` and a depth of `3` you would get a TOC for `h3`, `h4`, and `h5`.
Expand Down Expand Up @@ -104,7 +107,7 @@ If an `id` is found in one of the header tags that page-toc is configured to use
### Anchor Shortcode

Page TOC now includes a `anchor` shortcode that allows you to manually add linkable fragments in your content.
The shortcode will automatically generate the link if no options are provided. Alternatively you can use the bbode syntax of `anchor="some-custom-id"` or you can explicity set it. You can also set a `prefix` and let the shortcode autogenerate the rest.
The shortcode will automatically generate the link if no options are provided. Alternatively you can use the BBCode syntax of `anchor="some-custom-id"` or you can explicity set it. You can also set a `prefix` and let the shortcode autogenerate the rest.

For example:

Expand Down
14 changes: 13 additions & 1 deletion blueprints.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Page Toc
type: plugin
slug: page-toc
version: 3.2.2
version: 3.2.3
description: Generate a table of contents and anchors from a page
icon: list
author:
Expand Down Expand Up @@ -50,6 +50,12 @@ form:
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
templates:
type: selectize
label: PLUGIN_PAGE_TOC.ACTIVE_FOR_TEMPLATES
help: PLUGIN_PAGE_TOC.ACTIVE_FOR_TEMPLATES_HELP
validate:
type: commalist

toc_section:
type: section
Expand Down Expand Up @@ -84,6 +90,12 @@ form:
type: text
label: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES
help: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES_HELP
tags:
type: selectize
label: PLUGIN_PAGE_TOC.ALLOWED_HTML_TAGS
help: PLUGIN_PAGE_TOC.ALLOWED_HTML_TAGS_HELP
validate:
type: commalist

anchors_section:
type: section
Expand Down
8 changes: 8 additions & 0 deletions blueprints/page-toc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ form:
label: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES
help: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES_HELP
data-default@: ['\Grav\Plugin\PageTOCPlugin::configVar', 'hclass']
header.page-toc.tags:
toggleable: true
type: selectize
label: PLUGIN_PAGE_TOC.ALLOWED_HTML_TAGS
help: PLUGIN_PAGE_TOC.ALLOWED_HTML_TAGS_HELP
data-default@: ['\Grav\Plugin\PageTOCPlugin::configVar', 'tags']
validate:
type: commalist

header.page-toc-anchors-section:
type: section
Expand Down
17 changes: 15 additions & 2 deletions classes/HtmlHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use ArrayIterator;
use DOMDocument;
use DomElement;
use DomNode;
use DOMXPath;

/**
Expand All @@ -31,8 +32,8 @@ protected function getHTMLParser($markup)
{
libxml_use_internal_errors(true);
$domDocument = new \DOMDocument();
$html = "<page-toc>$markup</page-toc>";
$domDocument->loadHTML(mb_encode_numericentity($html, [0x80, 0x10FFFF, 0, ~0], 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$html = htmlspecialchars_decode(html_entity_decode("<page-toc>$markup</page-toc>", ENT_QUOTES | ENT_HTML5, 'UTF-8'), ENT_QUOTES);
$domDocument->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$domDocument->preserveWhiteSpace = true;
return $domDocument;
}
Expand Down Expand Up @@ -87,4 +88,16 @@ protected function traverseHeaderTags(DOMDocument $domDocument, int $topLevel, i
return new ArrayIterator([]);
}
}

protected function filteredInnerHTML(DOMNode $element, array $allowedTags): string
{
$innerHTML = "";
$children = $element->childNodes;

foreach ($children as $child) {
$innerHTML .= $element->ownerDocument->saveHTML($child);
}

return strip_tags($innerHTML, $allowedTags);
}
}
5 changes: 3 additions & 2 deletions classes/TocGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function __construct()
* @param int $depth Depth (1 through 6)
* @return ItemInterface KNP Menu
*/
public function getMenu(string $markup, int $topLevel = 1, int $depth = 6): ItemInterface
public function getMenu(string $markup, int $topLevel = 1, int $depth = 6, array $allowedTags = []): ItemInterface
{
$menu = $this->menuFactory->createItem(static::DEFAULT_NAME);

Expand Down Expand Up @@ -97,7 +97,8 @@ public function getMenu(string $markup, int $topLevel = 1, int $depth = 6): Item
$lastElem = $parent->addChild(
$node->getAttribute('id'),
[
'label' => $node->getAttribute('title') ?: $node->textContent,
'label' => $node->getAttribute('title') ?:
($allowedTags ? $this->filteredInnerHTML($node, $allowedTags) : $node->textContent) ,
'uri' => '#' . $node->getAttribute('id')
]
);
Expand Down
40 changes: 40 additions & 0 deletions languages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ en:
ACTIVE_BY_DEFAULT: 'Anchors generated by default'
ACTIVE_BY_DEFAULT_PAGE: 'Anchors generated for this page'
ACTIVE_BY_DEFAULT_PAGE_HELP: 'If the default setting is disabled, you can enable on this page, or vice versa'
ACTIVE_FOR_TEMPLATES: 'Anchors generated for these templates'
ACTIVE_FOR_TEMPLATES_HELP: 'Only relevant if default (site-wide) anchor generation is disabled'
TOC_SECTION: 'Table of Contents Configuration'
START_TOC_HEADERS: 'Start TOC headers'
START_TOC_HEADERS_HELP: 'The Header level to start the TOC from'
DEPTH_TOC_HEADERS: 'Depth of TOC headers'
DEPTH_TOC_HEADERS_HELP: 'The number of headers levels from the ''start'' to include in the TOC'
HEADER_CSS_CLASSES: 'Header CSS classes'
HEADER_CSS_CLASSES_HELP: 'Any custom classes to add to the header tags when IDs for slugs are added'
ALLOWED_HTML_TAGS: 'Whitelisted HTML tags'
ALLOWED_HTML_TAGS_HELP: 'These tags if present in the headers will be preserved in the TOC'
ANCHORS_SECTION: 'Anchors Configuration'
START_ANCHOR_HEADERS: 'Start Anchor headers'
DEPTH_ANCHOR_HEADERS: 'Depth of Anchor headers'
Expand All @@ -36,3 +40,39 @@ en:
SLUG_PREFIX_HELP: 'A prefix used in front of generated slugs'
PAGE_ANCHORS_SECTION: 'Page Anchors Configuration'
COPY_TO_CLIPBOARD: 'Copy to Clipboard'
fr:
PLUGIN_PAGE_TOC:
TABLE_OF_CONTENTS: Table des matières
INCLUDE_CSS: 'Inclure le CSS'
ACTIVE_BY_DEFAULT: 'Ancres générées par défaut'
ACTIVE_BY_DEFAULT_PAGE: 'Ancres générées sur cette page'
ACTIVE_BY_DEFAULT_PAGE_HELP: 'Si les paramètres par défaut sont désactivés, vous pouvez les activer sur cette page ou vice-versa'
TOC_SECTION: 'Configuration de la table des matières'
START_TOC_HEADERS: 'Début des titres de la table des matières'
START_TOC_HEADERS_HELP: 'Le niveau de titre de référence de la table des matières'
DEPTH_TOC_HEADERS: 'Profondeur des titres de la table des matières'
DEPTH_TOC_HEADERS_HELP: 'Le nombre de sous-niveaux de titres dans la table des matières, à partir du niveau de référence'
HEADER_CSS_CLASSES: 'Classes CSS à utiliser pour les titres'
HEADER_CSS_CLASSES_HELP: 'Classes CSS à ajouter aux tags des titres quand les identifiants de slugs sont ajoutés'
ANCHORS_SECTION: 'Configuration des ancres'
START_ANCHOR_HEADERS: 'Début des ancres de titres'
DEPTH_ANCHOR_HEADERS: 'Profondeur des ancres de titres'
LINK_ANCHOR_HEADERS: 'Liens des ancres'
ARIA_LABEL: 'Aria Label'
ANCHORS_CLASS: 'Classes CSS personnalisées des ancres'
ANCHORS_CLASS_HELP: 'Classes CSS à ajouter aux tags des ancres'
ANCHORS_ICON: 'Symbole utilisé pour les icônes d''ancres'
ANCHORS_ICON_HELP: 'Peut être n''importe quel caractère, symbole, caractère unicode ou même un émoticône. Laissez ce champ vide si vous comptez utiliser du CSS.'
ANCHORS_POSITION: 'Position des ancres'
ANCHORS_POSITION_HELP: 'Position où afficher les ancres: avant ou après (valeurs acceptées: `before|after`)'
ANCHORS_COPY_TO_CLIPBOARD: 'Copier dans le presse-papiers'
ANCHORS_COPY_TO_CLIPBOARD_HELP: 'Lors du clic sur une ancre, cela copie également l''URL complète dans le presse-papiers. Utile pour partager/ouvrir dans un nouvel onglet'
BEFORE_TEXT: 'Avant le texte'
AFTER_TEXT: 'Après le texte'
SLUG_MAXLEN: 'Longueur maximale des slugs'
SLUG_MAXLEN_HELP: 'Longueur maximale des slugs utilisés pour les ancres'
SLUG_PREFIX: 'Préfixe des slugs'
SLUG_PREFIX_HELP: 'Un préfixe utilisé devant les slugs générés'
PAGE_ANCHORS_SECTION: 'Configuration des ancres de pages'
COPY_TO_CLIPBOARD: 'Copier dans le presse-papiers'

13 changes: 8 additions & 5 deletions page-toc.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,11 @@ public function onPageContentProcessed(Event $event)
$content = $page->content();
$shortcode_exists = preg_match($this->toc_regex, $content);
$active = $this->configVar('active', $page, false);
$activated_templates = $this->configVar('templates', $page, []);
$is_template_activated = in_array($page->template(), $activated_templates);

// Set ID anchors if needed
if ($active || $shortcode_exists) {
if ($active || $is_template_activated || $shortcode_exists) {
$this->registerTwigFunctions();
$markup_fixer = new MarkupFixer();
$content = $markup_fixer->fix($content, $this->getAnchorOptions($page));
Expand Down Expand Up @@ -143,9 +145,9 @@ public function registerTwigFunctions()
return $this->generator->getHtmlMenu($markup, $options['start'], $options['depth'], null, true);
}, ['is_safe' => ['html']]));

$twig->addFunction(new TwigFunction('toc_items', function ($markup, $start = null, $depth = null) {
$options = $this->getTocOptions(null, $start, $depth);
return $this->generator->getMenu($markup, $options['start'], $options['depth']);
$twig->addFunction(new TwigFunction('toc_items', function ($markup, $start = null, $depth = null, $tags = null) {
$options = $this->getTocOptions(null, $start, $depth, $tags);
return $this->generator->getMenu($markup, $options['start'], $options['depth'], $options['tags']);
}));

$twig->addFunction(new TwigFunction('add_anchors', function ($markup, $start = null, $depth = null) {
Expand Down Expand Up @@ -189,12 +191,13 @@ public function onBlueprintCreated(Event $event)
}
}

protected function getTocOptions(PageInterface $page = null, $start = null, $depth = null): array
protected function getTocOptions(PageInterface $page = null, $start = null, $depth = null, $tags = null): array
{
$page = $page ?? $this->grav['page'];
return [
'start' => $start ?? $this->configVar('start', $page,1),
'depth' => $depth ?? $this->configVar('depth', $page,6),
'tags' => $tags ?? $this->configVar('tags', $page,[]),
];
}

Expand Down
1 change: 1 addition & 0 deletions page-toc.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
enabled: true # Plugin enabled
include_css: true # Include CSS
active: true # Anchor IDs processed and generated for all pages
templates: # Templates for which anchors should be generated if default is disabled
start: 1 # Start header tag level (1 = h1) for TOC
depth: 6 # Depth from start (2 = 2 levels deep) for TOC
hclass: # Custom Header TOC styling classes
Expand Down
8 changes: 4 additions & 4 deletions templates/components/page-toc.html.twig
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{% import _self as self %}

{% macro toc_loop(items) %}

{% for item in items %}
{% set class = loop.first ? 'first' : loop.last ? 'last' : null %}
<li {% if class %}class="{{ class }}"{% endif %}>
<a href="{{ item.uri }}">{{ item.label }}</a>
<a href="{{ item.uri }}">{{ item.label | raw }}</a>
{% if item.children|length > 0 %}
<ul>
{{ self.toc_loop(item.children) }}
{{ _self.toc_loop(item.children) }}
</ul>
{% endif %}
</li>
Expand All @@ -20,7 +20,7 @@
{% if table_of_contents is not empty %}
<h4>{{ 'PLUGIN_PAGE_TOC.TABLE_OF_CONTENTS'|t }}</h4>
<ul>
{{ self.toc_loop(table_of_contents.children) }}
{{ _self.toc_loop(table_of_contents.children) }}
</ul>
{% endif %}
</div>
Expand Down

0 comments on commit db406a9

Please sign in to comment.