(Grav GitSync) Automatic Commit from dan
This commit is contained in:
parent
e96c352b5b
commit
b5968f0871
22 changed files with 316 additions and 23 deletions
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
title: 'Name change! - techsaviours.org becomes digitalprivacy.diy'
|
||||||
|
author: Dan
|
||||||
|
published: true
|
||||||
|
date: '10-06-2024 07:47'
|
||||||
|
taxonomy:
|
||||||
|
category:
|
||||||
|
- news
|
||||||
|
tag:
|
||||||
|
- 'DIGITAL PRIVACY'
|
||||||
|
- digitalprivacy
|
||||||
|
- DIY
|
||||||
|
- 'TECH SAVIOURS'
|
||||||
|
aura:
|
||||||
|
author: dan
|
||||||
|
---
|
||||||
|
|
||||||
|
# techsaviours.org becomes digitalprivacy.diy
|
||||||
|
We have changed the name to something more appropriate. The last announcement about _TECH SAVIOURS_ actually expressed something different, but it was also a very quick decision - just over a week ago, and basically everything is already in the pipeline.
|
||||||
|
The new name will simply be “**DIGITAL PRIVACY**” and the TLD will be **.DIY** (**D**o **I**t **Y**ourself). That's what it actually is - “Your digital privacy diy solutions”.
|
||||||
|
|
||||||
|
|
||||||
|
# What does it mean for you?
|
||||||
|
|
||||||
|
## Matrix
|
||||||
|
Matrix will be a brand new domain **@user:digitalprivacy.diy** and cannot simply be merged from @user:techsaviours.org to the new domain. A new registration is therefore mandatory - sorry for that.
|
||||||
|
It is already possible to register via https://chat.digitalprivacy.diy or `digitalprivacy.diy` via your favourite client (Custom server).
|
||||||
|
|
||||||
|
You must use the registration token `NjT8tY6CSR4yRHIH`. A token will be required for every registration from now on. A new token will be created approximately every month and will be published either on the website or on other platforms.
|
||||||
|
|
||||||
|
Also, if you get “***This room is too busy. Sorry, but you can't join it.***", we have enabled [limit_remote_rooms](https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#limit_remote_rooms) to block the heavy rooms like `#matrix:matrix.org`. We ended up with **complexity: 40**, which still allows you to join rooms with around 8000 users.
|
||||||
|
The idea of this instance, it's more about socializing in small rooms - talking just to your/our friends. We may even reduce the number if the database grows too fast and to make this instance less interesting for spammers.
|
||||||
|
If you want to join the big rooms, another instance is probably the better choice.
|
||||||
|
|
||||||
|
techsaviours.org will still be available and maintained until October 25, 2024. This gives you enough time to either choose a completely different instance or gradually move to the new domain.
|
||||||
|
|
||||||
|
## Forgejo
|
||||||
|
Forgejo will also be moved on Wednesday.
|
||||||
|
So you will need to change the URL one more time via `git remote set-url origin forgejo@git.digitalprivacy.diy:USER/REPO.git`, same thing like the last time when the move from [Gitea to Forgejo](https://digitalprivacy.diy/news/en/tech-saviours-news-28-04-2024) happened.
|
||||||
|
|
||||||
|
## Domain
|
||||||
|
Everything else is actually the same. Simply replace _techsaviours.org_ with `digitalprivacy.diy`.
|
||||||
|
You'll see slightly changes the next few days/weeks. You'll notice the redirections to ***.digitalprivacy.diy**.
|
||||||
|
|
||||||
|
## Mastodon
|
||||||
|
Also mastodon is already transferred to https://fosstodon.org/@digitalprivacy. You may have already noticed it.
|
||||||
|
We have enabled to delete every post created after 6 month ago. I don't know how often and how far back you scroll, but I think it makes more sense to delete posts that are no longer important. And therefore save Fosstodon and the entire Federation a little more storage (money). Maybe it will also leave a slightly smaller footprint on our planet by using less power.
|
||||||
|
|
||||||
|
|
||||||
|
# New Extra
|
||||||
|
There is also a new extra, but it is still “hidden” in the wiki. If anyone is interested in finding it. Have fun ;) But it will also be published very soon. It fits perfectly with the new domain in typical **DIY** manner, as mentioned:
|
||||||
|
|
||||||
|
> you will be able to check your devices/networks
|
||||||
|
|
||||||
|
That's it so far. I hope it's not too much trouble, but we think it's worth it.
|
||||||
|
I will also let you know when the move to **git.digitalprivacy.diy (forgejo)** is completed.
|
||||||
|
|
||||||
|
Welcome your new **DIGITAL PRIVACY .DIY** solutions and have a good start to the new week
|
||||||
|
Dan
|
|
@ -1,3 +1,9 @@
|
||||||
|
# v1.10.46
|
||||||
|
## 05/15/2024
|
||||||
|
|
||||||
|
1. [](#improved)
|
||||||
|
* Used Login's new `site_host` security setting for Admin password reset. Requires Login version `3.7.8+`
|
||||||
|
|
||||||
# v1.10.45
|
# v1.10.45
|
||||||
## 03/18/2024
|
## 03/18/2024
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: Admin Panel
|
name: Admin Panel
|
||||||
slug: admin
|
slug: admin
|
||||||
type: plugin
|
type: plugin
|
||||||
version: 1.10.45
|
version: 1.10.46
|
||||||
description: Adds an advanced administration panel to manage your site
|
description: Adds an advanced administration panel to manage your site
|
||||||
icon: empire
|
icon: empire
|
||||||
author:
|
author:
|
||||||
|
@ -17,7 +17,7 @@ license: MIT
|
||||||
dependencies:
|
dependencies:
|
||||||
- { name: grav, version: '>=1.7.42' }
|
- { name: grav, version: '>=1.7.42' }
|
||||||
- { name: form, version: '>=6.0.1' }
|
- { name: form, version: '>=6.0.1' }
|
||||||
- { name: login, version: '>=3.7.0' }
|
- { name: login, version: '>=3.7.8' }
|
||||||
- { name: email, version: '>=3.1.6' }
|
- { name: email, version: '>=3.1.6' }
|
||||||
- { name: flex-objects, version: '>=1.2.0' }
|
- { name: flex-objects, version: '>=1.2.0' }
|
||||||
|
|
||||||
|
|
|
@ -469,7 +469,15 @@ class LoginController extends AdminController
|
||||||
$fullname = $user->fullname ?: $username;
|
$fullname = $user->fullname ?: $username;
|
||||||
$author = $config->get('site.author.name', '');
|
$author = $config->get('site.author.name', '');
|
||||||
$sitename = $config->get('site.title', 'Website');
|
$sitename = $config->get('site.title', 'Website');
|
||||||
$reset_link = $this->getAbsoluteAdminUrl("/reset/u/{$username}/{$token}");
|
$reset_route = "/reset/u/{$username}/{$token}";
|
||||||
|
|
||||||
|
$site_host = $config->get('plugins.login.site_host');
|
||||||
|
if (!empty($site_host)) {
|
||||||
|
$admin = $this->getAdmin();
|
||||||
|
$reset_link = rtrim($site_host, '/') . '/' . trim($admin->base, '/') . '/' . ltrim($reset_route, '/');
|
||||||
|
} else {
|
||||||
|
$reset_link = $this->getAbsoluteAdminUrl($reset_route);
|
||||||
|
}
|
||||||
|
|
||||||
// For testing only!
|
// For testing only!
|
||||||
//Admin::DEBUG && Admin::addDebugMessage(sprintf('Reset link: %s', $reset_link));
|
//Admin::DEBUG && Admin::addDebugMessage(sprintf('Reset link: %s', $reset_link));
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
# v2.0.3.1
|
||||||
|
## 05/16/2024
|
||||||
|
|
||||||
|
1. [](#improved)
|
||||||
|
* Added missing `Y` date format option from blueprints (admin plugin)
|
||||||
|
|
||||||
|
|
||||||
|
# v2.0.3
|
||||||
|
## 05/15/2024
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Added a new `partials/archives-year.html.twig` example and instructions on how to display a year-only format.
|
||||||
|
|
||||||
# v2.0.2
|
# v2.0.2
|
||||||
## 12/02/2020
|
## 12/02/2020
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,35 @@ Copy the template file [templates/partials/archives.html.twig](templates/partial
|
||||||
|
|
||||||
You can now edit the override and tweak it however you prefer.
|
You can now edit the override and tweak it however you prefer.
|
||||||
|
|
||||||
|
# Archives by Year example
|
||||||
|
|
||||||
|
The default `archives_data` object will contain pages broken out into groupings based on the `date_display_format` which by default is `F Y`, for example (`May 2024`). If you want to display the archives by the "Year" only, rather than "Month Year", you need to modify the `data_display_format` in the `archives.yaml` configuration file:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
date_display_format: 'Y'
|
||||||
|
```
|
||||||
|
Now the data will be grouped by year only.
|
||||||
|
|
||||||
|
Next, you will need to override and modify the `partials/archives.html.twig` file, or alternatively point to the new example `partials/archives-year.html.twig` file. This is modified to use the following syntax:
|
||||||
|
|
||||||
|
```twig
|
||||||
|
<ul class="archives">
|
||||||
|
|
||||||
|
{% for year,items in archives_data %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ archives_url ?? base_url }}/{{ config.plugins.archives.taxonomy_names.year }}{{ config.system.param_sep }}{{ year|date(config.plugins.archives.taxonomy_values.year)|lower|e('url') }}">
|
||||||
|
{% if archives_show_count %}
|
||||||
|
<span class="label">{{ items|length }}</span>
|
||||||
|
{% endif %}
|
||||||
|
<span class="archive_date">{{ year }} </span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
This is very similar to the default `partials/archives.html.twig` with `month` changed to `year`.
|
||||||
|
|
||||||
# Updating
|
# Updating
|
||||||
|
|
||||||
As development for Archives continues, new versions may become available that add additional features and functionality, improve compatibility with newer Grav releases, and generally provide a better user experience. Updating Archives is easy, and can be done through Grav's GPM system, as well as manually.
|
As development for Archives continues, new versions may become available that add additional features and functionality, improve compatibility with newer Grav releases, and generally provide a better user experience. Updating Archives is easy, and can be done through Grav's GPM system, as well as manually.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name: Archives
|
name: Archives
|
||||||
version: 2.0.2
|
version: 2.0.3.1
|
||||||
type: plugin
|
type: plugin
|
||||||
slug: archives
|
slug: archives
|
||||||
description: The **Archives** plugin creates links for pages grouped by month/year
|
description: The **Archives** plugin creates links for pages grouped by month/year
|
||||||
|
@ -47,12 +47,13 @@ form:
|
||||||
label: Date Format
|
label: Date Format
|
||||||
default: 'jS M Y'
|
default: 'jS M Y'
|
||||||
options:
|
options:
|
||||||
'F jS Y': "January 1st 2014"
|
'F jS Y': "January 1st 2024"
|
||||||
'l jS of F': "Monday 1st of January"
|
'l jS of F': "Monday 1st of January"
|
||||||
'D, m M Y': "Mon, 01 Jan 2014"
|
'D, m M Y': "Mon, 01 Jan 2024"
|
||||||
'd-m-y': "01-01-14"
|
'd-m-y': "01-01-24"
|
||||||
'jS M Y': "10th Feb 2014"
|
'jS M Y': "10th Feb 2024"
|
||||||
'F Y': "Jan 2015"
|
'F Y': "Jan 2024"
|
||||||
|
'Y': "2024"
|
||||||
|
|
||||||
show_count:
|
show_count:
|
||||||
type: toggle
|
type: toggle
|
||||||
|
|
15
plugins/archives/hebe.json
Normal file
15
plugins/archives/hebe.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"project":"grav-plugin-archives",
|
||||||
|
"platforms":{
|
||||||
|
"grav":{
|
||||||
|
"nodes":{
|
||||||
|
"plugin":[
|
||||||
|
{
|
||||||
|
"source":"/",
|
||||||
|
"destination":"/user/plugins/archives"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
plugins/archives/templates/partials/archives-year.html.twig
Normal file
13
plugins/archives/templates/partials/archives-year.html.twig
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<ul class="archives">
|
||||||
|
|
||||||
|
{% for year,items in archives_data %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ archives_url ?? base_url }}/{{ config.plugins.archives.taxonomy_names.year }}{{ config.system.param_sep }}{{ year|date(config.plugins.archives.taxonomy_values.year)|lower|e('url') }}">
|
||||||
|
{% if archives_show_count %}
|
||||||
|
<span class="label">{{ items|length }}</span>
|
||||||
|
{% endif %}
|
||||||
|
<span class="archive_date">{{ year }} </span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
|
@ -1,3 +1,9 @@
|
||||||
|
# v3.7.9
|
||||||
|
## 05/15/2024
|
||||||
|
|
||||||
|
1. [](#improved)
|
||||||
|
* Added default `site_host:` entry to `login.yaml` configuration file
|
||||||
|
|
||||||
# v3.7.8.1
|
# v3.7.8.1
|
||||||
## 04/19/2024
|
## 04/19/2024
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: Login
|
name: Login
|
||||||
slug: login
|
slug: login
|
||||||
type: plugin
|
type: plugin
|
||||||
version: 3.7.8.1
|
version: 3.7.9
|
||||||
testing: false
|
testing: false
|
||||||
description: Enables user authentication and login screen.
|
description: Enables user authentication and login screen.
|
||||||
icon: sign-in
|
icon: sign-in
|
||||||
|
|
|
@ -4,6 +4,7 @@ redirect_to_login: false # If you try to access a page you do
|
||||||
redirect_after_login: false # Path to redirect to after a successful login
|
redirect_after_login: false # Path to redirect to after a successful login
|
||||||
redirect_after_logout: true # Path to redirect to after a successful logout
|
redirect_after_logout: true # Path to redirect to after a successful logout
|
||||||
session_user_sync: false # Sync session user with changes in stored user file
|
session_user_sync: false # Sync session user with changes in stored user file
|
||||||
|
site_host: # Site host to use for email links. Enhances security by ensuring links are to the correct host (e.g. https://foo.com)
|
||||||
|
|
||||||
route: '/login' # Specific route for Login page (default is '/login')
|
route: '/login' # Specific route for Login page (default is '/login')
|
||||||
route_after_login: '/' # Route to go to after login if enabled
|
route_after_login: '/' # Route to go to after login if enabled
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
# v3.2.4
|
||||||
|
## 05/16/2024
|
||||||
|
|
||||||
|
1. [](#improved)
|
||||||
|
* Updated Spanish translation [#40](https://github.com/trilbymedia/grav-plugin-page-toc/pulls/40)
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Reverted to use `mb_encode_nuericentity()` instead of `htmlspecialchars` / `iconv` approach to fix breaking UTF-8 characters
|
||||||
|
|
||||||
|
# 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
|
# v3.2.2
|
||||||
## 05/10/2023
|
## 05/10/2023
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ Here is the default configuration and an explanation of available options:
|
||||||
enabled: true # Plugin enabled
|
enabled: true # Plugin enabled
|
||||||
include_css: true # Include CSS
|
include_css: true # Include CSS
|
||||||
active: true # Anchor IDs processed and generated for all pages
|
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
|
start: 1 # Start header tag level (1 = h1) for TOC
|
||||||
depth: 6 # Depth from start (2 = 2 levels deep) for TOC
|
depth: 6 # Depth from start (2 = 2 levels deep) for TOC
|
||||||
hclass: # Custom Header TOC styling classes
|
hclass: # Custom Header TOC styling classes
|
||||||
|
@ -61,6 +62,8 @@ page-toc:
|
||||||
active: true
|
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.
|
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`.
|
For example if you had a start of `3` and a depth of `3` you would get a TOC for `h3`, `h4`, and `h5`.
|
||||||
|
@ -104,7 +107,7 @@ If an `id` is found in one of the header tags that page-toc is configured to use
|
||||||
### Anchor Shortcode
|
### Anchor Shortcode
|
||||||
|
|
||||||
Page TOC now includes a `anchor` shortcode that allows you to manually add linkable fragments in your content.
|
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:
|
For example:
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: Page Toc
|
name: Page Toc
|
||||||
type: plugin
|
type: plugin
|
||||||
slug: page-toc
|
slug: page-toc
|
||||||
version: 3.2.2
|
version: 3.2.4
|
||||||
description: Generate a table of contents and anchors from a page
|
description: Generate a table of contents and anchors from a page
|
||||||
icon: list
|
icon: list
|
||||||
author:
|
author:
|
||||||
|
@ -50,6 +50,12 @@ form:
|
||||||
0: PLUGIN_ADMIN.DISABLED
|
0: PLUGIN_ADMIN.DISABLED
|
||||||
validate:
|
validate:
|
||||||
type: bool
|
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:
|
toc_section:
|
||||||
type: section
|
type: section
|
||||||
|
@ -84,6 +90,12 @@ form:
|
||||||
type: text
|
type: text
|
||||||
label: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES
|
label: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES
|
||||||
help: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES_HELP
|
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:
|
anchors_section:
|
||||||
type: section
|
type: section
|
||||||
|
|
|
@ -55,6 +55,14 @@ form:
|
||||||
label: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES
|
label: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES
|
||||||
help: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES_HELP
|
help: PLUGIN_PAGE_TOC.HEADER_CSS_CLASSES_HELP
|
||||||
data-default@: ['\Grav\Plugin\PageTOCPlugin::configVar', 'hclass']
|
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:
|
header.page-toc-anchors-section:
|
||||||
type: section
|
type: section
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Grav\Plugin\PageToc;
|
||||||
use ArrayIterator;
|
use ArrayIterator;
|
||||||
use DOMDocument;
|
use DOMDocument;
|
||||||
use DomElement;
|
use DomElement;
|
||||||
|
use DomNode;
|
||||||
use DOMXPath;
|
use DOMXPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +32,7 @@ trait HtmlHelper
|
||||||
{
|
{
|
||||||
libxml_use_internal_errors(true);
|
libxml_use_internal_errors(true);
|
||||||
$domDocument = new \DOMDocument();
|
$domDocument = new \DOMDocument();
|
||||||
|
|
||||||
$html = "<page-toc>$markup</page-toc>";
|
$html = "<page-toc>$markup</page-toc>";
|
||||||
$domDocument->loadHTML(mb_encode_numericentity($html, [0x80, 0x10FFFF, 0, ~0], 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
$domDocument->loadHTML(mb_encode_numericentity($html, [0x80, 0x10FFFF, 0, ~0], 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
||||||
$domDocument->preserveWhiteSpace = true;
|
$domDocument->preserveWhiteSpace = true;
|
||||||
|
@ -87,4 +89,16 @@ trait HtmlHelper
|
||||||
return new ArrayIterator([]);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ class TocGenerator
|
||||||
* @param int $depth Depth (1 through 6)
|
* @param int $depth Depth (1 through 6)
|
||||||
* @return ItemInterface KNP Menu
|
* @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);
|
$menu = $this->menuFactory->createItem(static::DEFAULT_NAME);
|
||||||
|
|
||||||
|
@ -97,7 +97,8 @@ class TocGenerator
|
||||||
$lastElem = $parent->addChild(
|
$lastElem = $parent->addChild(
|
||||||
$node->getAttribute('id'),
|
$node->getAttribute('id'),
|
||||||
[
|
[
|
||||||
'label' => $node->getAttribute('title') ?: $node->textContent,
|
'label' => $node->getAttribute('title') ?:
|
||||||
|
($allowedTags ? $this->filteredInnerHTML($node, $allowedTags) : $node->textContent) ,
|
||||||
'uri' => '#' . $node->getAttribute('id')
|
'uri' => '#' . $node->getAttribute('id')
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,6 +8,8 @@ en:
|
||||||
ACTIVE_BY_DEFAULT: 'Anchors generated by default'
|
ACTIVE_BY_DEFAULT: 'Anchors generated by default'
|
||||||
ACTIVE_BY_DEFAULT_PAGE: 'Anchors generated for this page'
|
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_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'
|
TOC_SECTION: 'Table of Contents Configuration'
|
||||||
START_TOC_HEADERS: 'Start TOC headers'
|
START_TOC_HEADERS: 'Start TOC headers'
|
||||||
START_TOC_HEADERS_HELP: 'The Header level to start the TOC from'
|
START_TOC_HEADERS_HELP: 'The Header level to start the TOC from'
|
||||||
|
@ -15,9 +17,12 @@ en:
|
||||||
DEPTH_TOC_HEADERS_HELP: 'The number of headers levels from the ''start'' to include in the TOC'
|
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: 'Header CSS classes'
|
||||||
HEADER_CSS_CLASSES_HELP: 'Any custom classes to add to the header tags when IDs for slugs are added'
|
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'
|
ANCHORS_SECTION: 'Anchors Configuration'
|
||||||
START_ANCHOR_HEADERS: 'Start Anchor headers'
|
START_ANCHOR_HEADERS: 'Start Anchor headers'
|
||||||
DEPTH_ANCHOR_HEADERS: 'Depth of Anchor headers'
|
DEPTH_ANCHOR_HEADERS: 'Depth of Anchor headers'
|
||||||
|
DEPTH_ANCHOR_HEADERS_HELP: 'The number of header levels from the ''start'' to be displayed'
|
||||||
LINK_ANCHOR_HEADERS: 'Link Anchors'
|
LINK_ANCHOR_HEADERS: 'Link Anchors'
|
||||||
ARIA_LABEL: 'Aria Label'
|
ARIA_LABEL: 'Aria Label'
|
||||||
ANCHORS_CLASS: 'Custom CSS classes for anchors'
|
ANCHORS_CLASS: 'Custom CSS classes for anchors'
|
||||||
|
@ -36,3 +41,80 @@ en:
|
||||||
SLUG_PREFIX_HELP: 'A prefix used in front of generated slugs'
|
SLUG_PREFIX_HELP: 'A prefix used in front of generated slugs'
|
||||||
PAGE_ANCHORS_SECTION: 'Page Anchors Configuration'
|
PAGE_ANCHORS_SECTION: 'Page Anchors Configuration'
|
||||||
COPY_TO_CLIPBOARD: 'Copy to Clipboard'
|
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'
|
||||||
|
DEPTH_ANCHOR_HEADERS_HELP: 'Le nombre de niveaux de titres depuis le ''début'' à afficher'
|
||||||
|
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'
|
||||||
|
es:
|
||||||
|
PLUGIN_PAGE_TOC:
|
||||||
|
TABLE_OF_CONTENTS: Tabla de Contenidos
|
||||||
|
INCLUDE_CSS: 'Incluir CSS'
|
||||||
|
ACTIVE_BY_DEFAULT: 'Enlaces ancla generados por defecto'
|
||||||
|
ACTIVE_BY_DEFAULT_PAGE: 'Enlaces ancla generados para esta página'
|
||||||
|
ACTIVE_BY_DEFAULT_PAGE_HELP: 'Si la configuración por defecto está desactivada, puedes activarla en esta página, o viceversa'
|
||||||
|
ACTIVE_FOR_TEMPLATES: 'Enlaces ancla generados para estas plantillas'
|
||||||
|
ACTIVE_FOR_TEMPLATES_HELP: 'Solo es relevante si la generación de enlaces ancla predeterminada (para todo el sitio) está desactivada'
|
||||||
|
TOC_SECTION: 'Configuración de la Tabla de Contenidos'
|
||||||
|
START_TOC_HEADERS: 'Iniciar encabezados de TOC'
|
||||||
|
START_TOC_HEADERS_HELP: 'El nivel de encabezado desde el cual iniciar la TOC'
|
||||||
|
DEPTH_TOC_HEADERS: 'Profundidad de encabezados de TOC'
|
||||||
|
DEPTH_TOC_HEADERS_HELP: 'El número de niveles de encabezados desde el ''inicio'' a incluir en la TOC'
|
||||||
|
HEADER_CSS_CLASSES: 'Clases CSS de encabezado'
|
||||||
|
HEADER_CSS_CLASSES_HELP: 'Cualquier clase personalizada para agregar a las etiquetas de encabezado cuando se agreguen ID para los slugs'
|
||||||
|
ALLOWED_HTML_TAGS: 'Etiquetas HTML permitidas'
|
||||||
|
ALLOWED_HTML_TAGS_HELP: 'Estas etiquetas, si están presentes en los encabezados, se conservarán en la TOC'
|
||||||
|
ANCHORS_SECTION: 'Configuración de enlaces ancla'
|
||||||
|
START_ANCHOR_HEADERS: 'Iniciar encabezados de enlace ancla'
|
||||||
|
DEPTH_ANCHOR_HEADERS: 'Profundidad de encabezados de enlace ancla'
|
||||||
|
DEPTH_ANCHOR_HEADERS_HELP: 'El número de niveles de encabezados desde el ''inicio'' que se mostrarán'
|
||||||
|
LINK_ANCHOR_HEADERS: 'Enlaces de anclaje'
|
||||||
|
ARIA_LABEL: 'Etiqueta Aria'
|
||||||
|
ANCHORS_CLASS: 'Clases CSS personalizadas para enlaces ancla'
|
||||||
|
ANCHORS_CLASS_HELP: 'Cualquier clase personalizada para agregar a las etiquetas de enlace ancla'
|
||||||
|
ANCHORS_ICON: 'Símbolo del icono de enlace ancla'
|
||||||
|
ANCHORS_ICON_HELP: 'Puede ser cualquier carácter de texto, símbolo, carácter unicode o incluso emoji. déjalo en blanco si tienes la intención de estilizar con CSS.'
|
||||||
|
ANCHORS_POSITION: 'Posición del enlace ancla'
|
||||||
|
ANCHORS_POSITION_HELP: 'Posición para poner el enlace ancla, `antes|después`'
|
||||||
|
ANCHORS_COPY_TO_CLIPBOARD: 'Copiar al Portapapeles'
|
||||||
|
ANCHORS_COPY_TO_CLIPBOARD_HELP: 'Al hacer clic en un enlace ancla, también copiará al portapapeles la URL completa. Conveniente para compartir/abrir en una nueva pestaña'
|
||||||
|
BEFORE_TEXT: 'Texto antes'
|
||||||
|
AFTER_TEXT: 'Texto después'
|
||||||
|
SLUG_MAXLEN: 'Longitud máxima del Slug'
|
||||||
|
SLUG_MAXLEN_HELP: 'Longitud máxima de los slugs usados para los enlaces ancla'
|
||||||
|
SLUG_PREFIX: 'Prefijo del Slug'
|
||||||
|
SLUG_PREFIX_HELP: 'Un prefijo usado delante de los slugs generados'
|
||||||
|
PAGE_ANCHORS_SECTION: 'Configuración de enlaces ancla de Página'
|
||||||
|
COPY_TO_CLIPBOARD: 'Copiar al Portapapeles'
|
||||||
|
|
||||||
|
|
|
@ -89,9 +89,11 @@ class PageTOCPlugin extends Plugin
|
||||||
$content = $page->content();
|
$content = $page->content();
|
||||||
$shortcode_exists = preg_match($this->toc_regex, $content);
|
$shortcode_exists = preg_match($this->toc_regex, $content);
|
||||||
$active = $this->configVar('active', $page, false);
|
$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
|
// Set ID anchors if needed
|
||||||
if ($active || $shortcode_exists) {
|
if ($active || $is_template_activated || $shortcode_exists) {
|
||||||
$this->registerTwigFunctions();
|
$this->registerTwigFunctions();
|
||||||
$markup_fixer = new MarkupFixer();
|
$markup_fixer = new MarkupFixer();
|
||||||
$content = $markup_fixer->fix($content, $this->getAnchorOptions($page));
|
$content = $markup_fixer->fix($content, $this->getAnchorOptions($page));
|
||||||
|
@ -143,9 +145,9 @@ class PageTOCPlugin extends Plugin
|
||||||
return $this->generator->getHtmlMenu($markup, $options['start'], $options['depth'], null, true);
|
return $this->generator->getHtmlMenu($markup, $options['start'], $options['depth'], null, true);
|
||||||
}, ['is_safe' => ['html']]));
|
}, ['is_safe' => ['html']]));
|
||||||
|
|
||||||
$twig->addFunction(new TwigFunction('toc_items', function ($markup, $start = null, $depth = null) {
|
$twig->addFunction(new TwigFunction('toc_items', function ($markup, $start = null, $depth = null, $tags = null) {
|
||||||
$options = $this->getTocOptions(null, $start, $depth);
|
$options = $this->getTocOptions(null, $start, $depth, $tags);
|
||||||
return $this->generator->getMenu($markup, $options['start'], $options['depth']);
|
return $this->generator->getMenu($markup, $options['start'], $options['depth'], $options['tags']);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$twig->addFunction(new TwigFunction('add_anchors', function ($markup, $start = null, $depth = null) {
|
$twig->addFunction(new TwigFunction('add_anchors', function ($markup, $start = null, $depth = null) {
|
||||||
|
@ -189,12 +191,13 @@ class PageTOCPlugin extends Plugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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'];
|
$page = $page ?? $this->grav['page'];
|
||||||
return [
|
return [
|
||||||
'start' => $start ?? $this->configVar('start', $page,1),
|
'start' => $start ?? $this->configVar('start', $page,1),
|
||||||
'depth' => $depth ?? $this->configVar('depth', $page,6),
|
'depth' => $depth ?? $this->configVar('depth', $page,6),
|
||||||
|
'tags' => $tags ?? $this->configVar('tags', $page,[]),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
enabled: true # Plugin enabled
|
enabled: true # Plugin enabled
|
||||||
include_css: true # Include CSS
|
include_css: true # Include CSS
|
||||||
active: true # Anchor IDs processed and generated for all pages
|
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
|
start: 1 # Start header tag level (1 = h1) for TOC
|
||||||
depth: 6 # Depth from start (2 = 2 levels deep) for TOC
|
depth: 6 # Depth from start (2 = 2 levels deep) for TOC
|
||||||
hclass: # Custom Header TOC styling classes
|
hclass: # Custom Header TOC styling classes
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{% import _self as self %}
|
|
||||||
|
|
||||||
{% macro toc_loop(items) %}
|
{% macro toc_loop(items) %}
|
||||||
|
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
{% set class = loop.first ? 'first' : loop.last ? 'last' : null %}
|
{% set class = loop.first ? 'first' : loop.last ? 'last' : null %}
|
||||||
<li {% if class %}class="{{ class }}"{% endif %}>
|
<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 %}
|
{% if item.children|length > 0 %}
|
||||||
<ul>
|
<ul>
|
||||||
{{ self.toc_loop(item.children) }}
|
{{ _self.toc_loop(item.children) }}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
{% if table_of_contents is not empty %}
|
{% if table_of_contents is not empty %}
|
||||||
<h4>{{ 'PLUGIN_PAGE_TOC.TABLE_OF_CONTENTS'|t }}</h4>
|
<h4>{{ 'PLUGIN_PAGE_TOC.TABLE_OF_CONTENTS'|t }}</h4>
|
||||||
<ul>
|
<ul>
|
||||||
{{ self.toc_loop(table_of_contents.children) }}
|
{{ _self.toc_loop(table_of_contents.children) }}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue