Skip to content

Commit c310707

Browse files
authored
[BUGFIX] Fix scrolling behavior for confvals (#975)
And fix permalink display. Add tests for permalinks Resolves #973
1 parent 2dcc6d0 commit c310707

File tree

26 files changed

+1038
-674
lines changed

26 files changed

+1038
-674
lines changed

Documentation-rendertest/Confval/Index.rst

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
confval
77
=======
88

9+
Permalink to confval: `array of cObjects <https://docs.typo3.org/permalink/rendertest:confval-case-array>`_.
10+
911
.. toctree::
1012
:glob:
1113

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.. include:: /Includes.rst.txt
2+
3+
======================
4+
Confvals with subtrees
5+
======================
6+
7+
.. confval-menu::
8+
:name: x-case-properties
9+
:caption: TypoScript Case Properties
10+
:display: table
11+
:type:
12+
13+
.. confval:: array of cObjects
14+
:name: x-case-array
15+
:type: cObject
16+
:searchFacet: TypoScript
17+
18+
Array of cObjects. Use this to define cObjects for the different
19+
values of `cobj-case-key`. If `cobj-case-key` has a certain value,
20+
the according cObject will be rendered. The cObjects can have any name, but not
21+
the names of the other properties of the cObject CASE.
22+
23+
.. confval:: cache
24+
:name: x-case-cache
25+
:type: cache
26+
:searchFacet: TypoScript
27+
28+
See for details.

Documentation-rendertest/guides.xml

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
xsi:schemaLocation="https://www.phpdoc.org/guides ../vendor/phpdocumentor/guides-cli/resources/schema/guides.xsd"
55
links-are-relative="true">
66
<extension class="\T3Docs\Typo3DocsTheme\DependencyInjection\Typo3DocsThemeExtension"
7+
interlink-shortcode="rendertest"
78
typo3-core-preferred="stable"
89
confval-default="TCA"
910
/>

packages/typo3-docs-theme/assets/js/scrolling.js

+8-20
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,29 @@ document.addEventListener("DOMContentLoaded", function () {
33
const header = document.querySelector("header");
44
const headerHeight = header ? header.offsetHeight : 80; // Default fallback
55

6-
document.querySelectorAll(".section").forEach(section => {
6+
document.querySelectorAll("[id]").forEach(el => {
77
section.style.scrollMarginTop = `${headerHeight + 10}px`; // Extra space for visibility
88
});
99
}
1010

1111
function scrollToAnchor() {
1212
const hash = window.location.hash.substring(1); // Get anchor without #
13-
if (!hash) return;
13+
if (!hash || hash === "top") {
14+
window.scrollTo({ top: 0, behavior: "smooth" });
15+
return;
16+
}
1417

1518
const target = document.getElementById(hash);
1619
if (target) {
17-
// Check if the target is the first main section (h1)
18-
const isFirstSection = target.closest(".section")?.querySelector("h1") !== null;
19-
20-
if (isFirstSection) {
21-
window.scrollTo({
22-
top: 0,
23-
behavior: "smooth"
24-
});
25-
} else {
26-
setTimeout(() => {
27-
target.scrollIntoView({ behavior: "smooth", block: "start" });
28-
}, 50); // Delay ensures styles apply
29-
}
20+
setTimeout(() => {
21+
target.scrollIntoView({ behavior: "smooth", block: "start" });
22+
}, 50); // Delay ensures styles apply
3023
}
3124
}
3225

33-
// Adjust scroll margin on load
3426
adjustScrollMargin();
35-
36-
// Handle initial anchor scrolling
3727
setTimeout(scrollToAnchor, 100); // Slight delay for rendering
3828

39-
// Handle clicks on internal links
4029
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
4130
anchor.addEventListener("click", function (e) {
4231
e.preventDefault();
@@ -46,6 +35,5 @@ document.addEventListener("DOMContentLoaded", function () {
4635
});
4736
});
4837

49-
// Adjust when resizing (e.g., switching between desktop & mobile)
5038
window.addEventListener("resize", adjustScrollMargin);
5139
});

packages/typo3-docs-theme/resources/public/js/theme.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/typo3-docs-theme/resources/template/body/directive/confval-menu.html.twig

+7-5
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,10 @@
154154
<div class="caption">{{ node.caption }}</div>
155155
{%- endif %}
156156
{% endmacro %}
157-
157+
<a id="{{ node.anchor }}"></a>
158158
{% import _self as macros %}
159159
{% if node.display=='list' %}
160-
<div class="mb-4" id="{{ node.anchor }}">
160+
<div class="mb-4">
161161
{{ macros.renderCaption(node) }}
162162
<ul>
163163
{% for entry in node.confvals %}
@@ -166,7 +166,7 @@
166166
</ul>
167167
</div>
168168
{% elseif node.display=='tree' %}
169-
<div class="directory-tree mb-4" id="{{ node.anchor }}">
169+
<div class="directory-tree mb-4">
170170
{{ macros.renderCaption(node) }}
171171
<ul>
172172
{% for entry in node.confvals %}
@@ -175,7 +175,7 @@
175175
</ul>
176176
</div>
177177
{% else %}
178-
<div class="table-responsive confval-table" id="{{ node.anchor }}">
178+
<div class="table-responsive confval-table">
179179
<table class="table table-hover caption-top">
180180
{%- if node.caption %}<caption>{{ node.caption }}</caption>{% endif %}
181181
<thead>
@@ -202,9 +202,11 @@
202202
</div>
203203
{% endif %}
204204
{% for child in node.children %}
205+
{% do setBackAnchor(node.anchor) %}
205206
{% if child.isConfval %}
206-
{% include "body/directive/confval.html.twig" with {'node': child, 'backAnchor': node.anchor } %}
207+
{% include "body/directive/confval.html.twig" with {'node': child } %}
207208
{% else %}
208209
{{ renderNode(child) }}
209210
{% endif %}
211+
{% do setBackAnchor('') %}
210212
{% endfor %}

packages/typo3-docs-theme/resources/template/body/directive/confval.html.twig

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
{% set resolvedBackAnchor = backAnchor is defined ? backAnchor : getBackAnchor() %}
12
<section data-search-title="{{ node.plainContent }}"
23
data-search-id="{{ node.anchor }}"
34
data-search-facet="{{ filterAllowedSearchFacets(renderNode(node.additionalOptions.searchFacet)|default(getSettings('confval_default'))) }}"
45
class="confval-section"
6+
id="{{ node.anchor }}"
57
>
68
<h3 class="sr-only">{{ node.plainContent }}</h3>
79
<dl class="confval">
8-
<dt{% if not node.noindex %} id="{{ node.anchor }}"{% endif %}
10+
<dt{% if not node.noindex %} {% endif %}
911
class="d-flex justify-content-between">
1012
<div class="confval-header flex-grow-1">
1113
<code class="sig-name descname"><span
@@ -15,7 +17,6 @@
1517
data-bs-toggle="modal"
1618
data-bs-target="#linkReferenceModal"
1719
data-id="{{ node.anchor }}"
18-
data-rstCode="{{ getRstCodeForLink(node) }}"
1920
title="Reference this configuration value"><i
2021
class="fa-solid fa-paragraph"></i></a>
2122
{% else %}
@@ -25,8 +26,8 @@
2526
{% endif -%}
2627
</div>
2728
<div class="confval-back-to-top">
28-
{%- if backAnchor %}
29-
<a href="#{{ backAnchor }}" class="backToList"
29+
{%- if resolvedBackAnchor %}
30+
<a href="#{{ resolvedBackAnchor }}" class="backToList"
3031
title="Back to list"><i
3132
class="fa-solid fa-angles-up fa-xs"></i></a>
3233
{% else %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace T3Docs\Typo3DocsTheme\Twig;
4+
5+
final class ContextRegistry
6+
{
7+
/**
8+
* @var array<string, string>
9+
*/
10+
private static array $store = [];
11+
12+
public static function set(string $key, string $value): void
13+
{
14+
self::$store[$key] = $value;
15+
}
16+
17+
public static function get(string $key): ?string
18+
{
19+
return self::$store[$key] ?? null;
20+
}
21+
}

packages/typo3-docs-theme/src/Twig/TwigExtension.php

+16
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ public function getFunctions(): array
102102
new TwigFunction('getPermalink', $this->getPermalink(...), ['is_safe' => ['html'], 'needs_context' => true]),
103103
new TwigFunction('getSingleHtmlLink', $this->getSingleHtmlLink(...), ['is_safe' => ['html'], 'needs_context' => true]),
104104
new TwigFunction('getTopPageLink', $this->getTopPageLink(...), ['is_safe' => ['html'], 'needs_context' => true]),
105+
new TwigFunction('setBackAnchor', $this->setBackAnchor(...), ['needs_context' => true]),
106+
new TwigFunction('getBackAnchor', $this->getBackAnchor(...), ['needs_context' => true]),
105107
];
106108
}
107109

@@ -790,5 +792,19 @@ public function isRenderedForDeployment(): bool
790792

791793
return false;
792794
}
795+
/**
796+
* @param array{env: RenderContext} $context
797+
*/
798+
public function setBackAnchor(array $context, string $value): void
799+
{
800+
ContextRegistry::set('backAnchor', $value);
801+
}
793802

803+
/**
804+
* @param array{env: RenderContext} $context
805+
*/
806+
public function getBackAnchor(array $context): ?string
807+
{
808+
return ContextRegistry::get('backAnchor');
809+
}
794810
}

tests/Integration/tests/confval/confval-basic/expected/index.html

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
<!-- content start -->
22
<section class="section" id="confval">
33
<h1>Confval<a class="headerlink" href="#confval" data-bs-toggle="modal" data-bs-target="#linkReferenceModal" title="Reference this headline"><i class="fa-solid fa-paragraph"></i></a></h1>
4+
5+
<p>Permalink to confval: <a href="#confval-demo">demo</a>.</p>
6+
47
<section data-search-title="demo"
58
data-search-id="confval-demo"
69
data-search-facet="Option"
710
class="confval-section"
11+
id="confval-demo"
812
>
913
<h3 class="sr-only">demo</h3>
1014
<dl class="confval">
11-
<dt id="confval-demo" class="d-flex justify-content-between">
15+
<dt class="d-flex justify-content-between">
1216
<div class="confval-header flex-grow-1">
1317
<code class="sig-name descname"><span
1418
class="pre">demo</span></code>
1519
<a class="headerlink" href="#confval-demo"
1620
data-bs-toggle="modal"
1721
data-bs-target="#linkReferenceModal"
1822
data-id="confval-demo"
19-
data-rstCode=":ref:`demo &lt;somemanual:confval-demo&gt;`"
2023
title="Reference this configuration value"><i
2124
class="fa-solid fa-paragraph"></i></a>
2225
</div>
@@ -40,24 +43,24 @@ <h3 class="sr-only">demo</h3>
4043
</dl>
4144
</section>
4245

43-
<p>See also <a href="#confval-demo">demo</a> or <a href="#confval-demo">demo</a>.</p>
46+
<p>See also <a href="https://docs.typo3.org/permalink/test:confval-demo"></a> or <a href="#confval-demo">demo</a>.</p>
4447

4548
<section data-search-title="demo"
4649
data-search-id="confval-some-other-demo"
4750
data-search-facet="Option"
4851
class="confval-section"
52+
id="confval-some-other-demo"
4953
>
5054
<h3 class="sr-only">demo</h3>
5155
<dl class="confval">
52-
<dt id="confval-some-other-demo" class="d-flex justify-content-between">
56+
<dt class="d-flex justify-content-between">
5357
<div class="confval-header flex-grow-1">
5458
<code class="sig-name descname"><span
5559
class="pre">demo</span></code>
5660
<a class="headerlink" href="#confval-some-other-demo"
5761
data-bs-toggle="modal"
5862
data-bs-target="#linkReferenceModal"
5963
data-id="confval-some-other-demo"
60-
data-rstCode=":ref:`demo &lt;somemanual:confval-some-other-demo&gt;`"
6164
title="Reference this configuration value"><i
6265
class="fa-solid fa-paragraph"></i></a>
6366
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<guides xmlns="https://www.phpdoc.org/guides"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="https://www.phpdoc.org/guides vendor/phpdocumentor/guides-cli/resources/schema/guides.xsd"
5+
links-are-relative="true"
6+
theme="typo3docs"
7+
>
8+
9+
<extension class="\T3Docs\Typo3DocsTheme\DependencyInjection\Typo3DocsThemeExtension"
10+
interlink-shortcode="test"
11+
/>
12+
<extension
13+
class="\T3Docs\GuidesExtension\DependencyInjection\Typo3GuidesExtension"/>
14+
<output-format>interlink</output-format>
15+
<output-format>html</output-format>
16+
<output-format>singlepage</output-format>
17+
</guides>

tests/Integration/tests/confval/confval-basic/input/index.rst

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Confval
33
=======
44

5+
Permalink to confval: `demo <https://docs.typo3.org/permalink/test:confval-demo>`_.
6+
57
.. confval:: demo
68
:type: string
79
:default: ``"Hello World"``

tests/Integration/tests/confval/confval-duplicate-with-name/expected/anotherDomain.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ <h1>Confval in another domain<a class="headerlink" href="#confval-in-another-dom
55
data-search-id="confval-another-demo"
66
data-search-facet="Option"
77
class="confval-section"
8+
id="confval-another-demo"
89
>
910
<h3 class="sr-only">demo</h3>
1011
<dl class="confval">
11-
<dt id="confval-another-demo" class="d-flex justify-content-between">
12+
<dt class="d-flex justify-content-between">
1213
<div class="confval-header flex-grow-1">
1314
<code class="sig-name descname"><span
1415
class="pre">demo</span></code>
1516
<a class="headerlink" href="#confval-another-demo"
1617
data-bs-toggle="modal"
1718
data-bs-target="#linkReferenceModal"
1819
data-id="confval-another-demo"
19-
data-rstCode=":ref:`demo &lt;somemanual:confval-another-demo&gt;`"
2020
title="Reference this configuration value"><i
2121
class="fa-solid fa-paragraph"></i></a>
2222
</div>

tests/Integration/tests/confval/confval-duplicate-with-name/expected/index.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ <h1>Confval<a class="headerlink" href="#confval" data-bs-toggle="modal" data-bs-
55
data-search-id="confval-demo"
66
data-search-facet="Option"
77
class="confval-section"
8+
id="confval-demo"
89
>
910
<h3 class="sr-only">demo</h3>
1011
<dl class="confval">
11-
<dt id="confval-demo" class="d-flex justify-content-between">
12+
<dt class="d-flex justify-content-between">
1213
<div class="confval-header flex-grow-1">
1314
<code class="sig-name descname"><span
1415
class="pre">demo</span></code>
1516
<a class="headerlink" href="#confval-demo"
1617
data-bs-toggle="modal"
1718
data-bs-target="#linkReferenceModal"
1819
data-id="confval-demo"
19-
data-rstCode=":ref:`demo &lt;somemanual:confval-demo&gt;`"
2020
title="Reference this configuration value"><i
2121
class="fa-solid fa-paragraph"></i></a>
2222
</div>

tests/Integration/tests/confval/confval-duplicate/expected/anotherDomain.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ <h1>Confval in another domain<a class="headerlink" href="#confval-in-another-dom
55
data-search-id="confval-demo"
66
data-search-facet="Option"
77
class="confval-section"
8+
id="confval-demo"
89
>
910
<h3 class="sr-only">demo</h3>
1011
<dl class="confval">
11-
<dt id="confval-demo" class="d-flex justify-content-between">
12+
<dt class="d-flex justify-content-between">
1213
<div class="confval-header flex-grow-1">
1314
<code class="sig-name descname"><span
1415
class="pre">demo</span></code>
1516
<a class="headerlink" href="#confval-demo"
1617
data-bs-toggle="modal"
1718
data-bs-target="#linkReferenceModal"
1819
data-id="confval-demo"
19-
data-rstCode=":ref:`demo &lt;somemanual:confval-demo&gt;`"
2020
title="Reference this configuration value"><i
2121
class="fa-solid fa-paragraph"></i></a>
2222
</div>

tests/Integration/tests/confval/confval-duplicate/expected/index.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ <h1>Confval<a class="headerlink" href="#confval" data-bs-toggle="modal" data-bs-
55
data-search-id="confval-demo"
66
data-search-facet="Option"
77
class="confval-section"
8+
id="confval-demo"
89
>
910
<h3 class="sr-only">demo</h3>
1011
<dl class="confval">
11-
<dt id="confval-demo" class="d-flex justify-content-between">
12+
<dt class="d-flex justify-content-between">
1213
<div class="confval-header flex-grow-1">
1314
<code class="sig-name descname"><span
1415
class="pre">demo</span></code>
1516
<a class="headerlink" href="#confval-demo"
1617
data-bs-toggle="modal"
1718
data-bs-target="#linkReferenceModal"
1819
data-id="confval-demo"
19-
data-rstCode=":ref:`demo &lt;somemanual:confval-demo&gt;`"
2020
title="Reference this configuration value"><i
2121
class="fa-solid fa-paragraph"></i></a>
2222
</div>

0 commit comments

Comments
 (0)