Skip to content

Commit 7811ea7

Browse files
authored
[TASK] Support Markdown in ViewHelper Descriptions (#961)
1 parent d5aef67 commit 7811ea7

File tree

8 files changed

+575
-161
lines changed

8 files changed

+575
-161
lines changed

Documentation-rendertest/ViewHelpers/resources/global_viewhelpers_demo.json

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,102 @@
11
{
22
"namespace": "http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers",
33
"viewHelpers": {
4+
45
"split": {
56
"className": "TYPO3Fluid\\Fluid\\ViewHelpers\\SplitViewHelper",
67
"namespace": "TYPO3Fluid\\Fluid\\ViewHelpers",
78
"name": "SplitViewHelper",
89
"tagName": "split",
9-
"documentation": "The SplitViewHelper splits a string by the specified separator, which\nresults in an array. The number of values in the resulting array can\nbe limited with the limit parameter, which results in an array where\nthe last item contains the remaining unsplit string.\nThis ViewHelper mimicks PHP's :php:`explode()` function.\n\nExamples\n========\n\nSplit with a separator\n-----------------------\n\n::\n\n <f:split value=\"1,5,8\" separator=\",\" />\n.. code-block:: text\n {0: '1', 1: '5', 2: '8'}\n\nSplit using tag content as value\n--------------------------------\n\n::\n\n <f:split separator=\"-\">1-5-8</f:split>\n.. code-block:: text\n {0: '1', 1: '5', 2: '8'}\n\nSplit with a limit\n-------------------\n\n::\n\n <f:split value=\"1,5,8\" separator=\",\" limit=\"2\" />\n.. code-block:: text\n {0: '1', 1: '5,8'}",
10-
"xmlNamespace": "http://typo3.org/ns/TYPO3Fluid/Fluid/ViewHelpers",
11-
"docTags": {},
10+
"documentation": "The SplitViewHelper splits a string by the specified separator, which\nresults in an array. The number of values in the resulting array can\nbe limited with the limit parameter, which results in an array where\nthe last item contains the remaining unsplit string.\n\nThis ViewHelper mimicks PHP's :php:`explode()` function.\n\nThe following examples store the result in a variable because an array cannot\nbe outputted directly in a template.\n\nExamples\n========\n\nSplit with a separator\n-----------------------\n::\n\n <f:variable name=\"result\"><f:split value=\"1,5,8\" separator=\",\" \/><\/f:variable>\n\n.. code-block:: text\n\n {0: '1', 1: '5', 2: '8'}\n\n\nSplit using tag content as value\n--------------------------------\n\n::\n\n <f:variable name=\"result\"><f:split separator=\"-\">1-5-8<\/f:split><\/f:variable>\n\n.. code-block:: text\n\n {0: '1', 1: '5', 2: '8'}\n\n\nSplit with a limit\n-------------------\n\n::\n\n <f:variable name=\"result\"><f:split value=\"1,5,8\" separator=\",\" limit=\"2\" \/><\/f:variable>\n\n.. code-block:: text\n\n {0: '1', 1: '5,8'}",
11+
"xmlNamespace": "http:\/\/typo3.org\/ns\/TYPO3Fluid\/Fluid\/ViewHelpers",
12+
"docTags": [],
1213
"argumentDefinitions": {
1314
"value": {
1415
"name": "value",
1516
"type": "string",
1617
"description": "The string to explode",
1718
"required": false,
18-
"defaultValue": "",
19+
"defaultValue": null,
1920
"escape": null
2021
},
2122
"separator": {
2223
"name": "separator",
2324
"type": "string",
2425
"description": "Separator string to explode with",
2526
"required": true,
27+
"defaultValue": null,
2628
"escape": null
2729
},
2830
"limit": {
2931
"name": "limit",
3032
"type": "int",
3133
"description": "If limit is positive, a maximum of $limit items will be returned. If limit is negative, all items except for the last $limit items will be returned. 0 will be treated as 1.",
3234
"required": false,
33-
"defaultValue": 0,
35+
"defaultValue": 9223372036854775807,
3436
"escape": null
3537
}
3638
},
37-
"allowsArbitraryArguments": false
39+
"allowsArbitraryArguments": false,
40+
"nameWithoutSuffix": "Split",
41+
"namespaceWithoutSuffix": "TYPO3Fluid\\Fluid",
42+
"uri": "Global\/Split"
3843
},
39-
"link.external":{
44+
"link.external": {
4045
"className": "TYPO3\\CMS\\Fluid\\ViewHelpers\\Link\\ExternalViewHelper",
4146
"namespace": "TYPO3\\CMS\\Fluid\\ViewHelpers",
4247
"name": "Link\\ExternalViewHelper",
4348
"tagName": "link.external",
44-
"documentation": "A ViewHelper for creating links to external targets.\n\nExamples\n========\n\nDefault\n-------\n::\n\n <f:link.external uri=\"https://www.typo3.org\" target=\"_blank\">external link</f:link.external>\n\nOutput::\n\n <a href=\"https://www.typo3.org\" target=\"_blank\">external link</a>\n\nCustom default scheme\n---------------------\n\n::\n\n <f:link.external uri=\"typo3.org\" defaultScheme=\"ftp\">external ftp link</f:link.external>\n\nOutput::\n\n <a href=\"ftp://typo3.org\">external ftp link</a>",
45-
"xmlNamespace": "http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers",
46-
"docTags": {},
49+
"documentation": "ViewHelper for creating links to external targets.\n\n```\n <f:link.external uri=\"https:\/\/www.typo3.org\" target=\"_blank\">external link<\/f:link.external>\n```",
50+
"xmlNamespace": "http:\/\/typo3.org\/ns\/TYPO3\/CMS\/Fluid\/ViewHelpers",
51+
"docTags": {
52+
"@see": "https:\/\/docs.typo3.org\/permalink\/t3viewhelper:typo3-fluid-link-external"
53+
},
4754
"argumentDefinitions": {
55+
"additionalAttributes": {
56+
"name": "additionalAttributes",
57+
"type": "array",
58+
"description": "Additional tag attributes. They will be added directly to the resulting HTML tag.",
59+
"required": false,
60+
"defaultValue": null,
61+
"escape": null
62+
},
63+
"data": {
64+
"name": "data",
65+
"type": "array",
66+
"description": "Additional data-* attributes. They will each be added with a \"data-\" prefix.",
67+
"required": false,
68+
"defaultValue": null,
69+
"escape": null
70+
},
71+
"aria": {
72+
"name": "aria",
73+
"type": "array",
74+
"description": "Additional aria-* attributes. They will each be added with a \"aria-\" prefix.",
75+
"required": false,
76+
"defaultValue": null,
77+
"escape": null
78+
},
4879
"uri": {
4980
"name": "uri",
5081
"type": "string",
5182
"description": "The URI that will be put in the href attribute of the rendered link tag",
5283
"required": true,
5384
"defaultValue": null,
5485
"escape": null
86+
},
87+
"defaultScheme": {
88+
"name": "defaultScheme",
89+
"type": "string",
90+
"description": "Scheme the href attribute will be prefixed with if specified $uri does not contain a scheme already",
91+
"required": false,
92+
"defaultValue": "https",
93+
"escape": null
5594
}
5695
},
57-
"allowsArbitraryArguments": true
96+
"allowsArbitraryArguments": true,
97+
"nameWithoutSuffix": "Link\\External",
98+
"namespaceWithoutSuffix": "TYPO3\\CMS\\Fluid",
99+
"uri": "Global\/Link\/External"
58100
},
59101
"deprecated":{
60102
"className": "TYPO3\\CMS\\Fluid\\ViewHelpers\\DeprecatedViewHelper",

packages/typo3-docs-theme/src/Directives/ViewHelperDirective.php

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
namespace T3Docs\Typo3DocsTheme\Directives;
1515

16+
use phpDocumentor\Guides\Markdown\MarkupLanguageParser;
17+
use phpDocumentor\Guides\Nodes\CodeNode;
18+
use phpDocumentor\Guides\Nodes\CollectionNode;
1619
use phpDocumentor\Guides\Nodes\Inline\PlainTextInlineNode;
1720
use phpDocumentor\Guides\Nodes\InlineCompoundNode;
1821
use phpDocumentor\Guides\Nodes\Node;
@@ -41,6 +44,7 @@ public function __construct(
4144
private readonly LoggerInterface $logger,
4245
private readonly Rule $startingRule,
4346
private readonly AnchorNormalizer $anchorNormalizer,
47+
private readonly MarkupLanguageParser $markupLanguageParser,
4448
GenericLinkProvider $genericLinkProvider,
4549
) {
4650
$genericLinkProvider->addGenericLink(self::NAME, ViewHelperNode::LINK_TYPE, ViewHelperNode::LINK_PREFIX);
@@ -150,24 +154,37 @@ public function getArgument(array $argumentDefinition, ViewHelperNode $viewHelpe
150154
*/
151155
private function getViewHelperNode(Directive $directive, array $data, array $sourceEdit, BlockContext $blockContext, bool $noindex): ViewHelperNode
152156
{
153-
$rstContent = $this->getString($data, 'documentation');
154-
$rstContentBlockContext = new BlockContext($blockContext->getDocumentParserContext(), $rstContent, false);
155-
$collectionNode = $this->startingRule->apply($rstContentBlockContext);
157+
$rawDocumentation = $this->getString($data, 'documentation');
156158
$description = [];
157-
foreach ($collectionNode->getValue() as $node) {
158-
if (!$node instanceof SectionNode) {
159-
$description[] = $node;
160-
}
161-
}
162159
$sections = [];
163160
$examples = [];
164-
foreach ($collectionNode->getValue() as $node) {
165-
if ($node instanceof SectionNode) {
166-
$title = $node->getTitle()->toString();
167-
if (stripos($title, 'example') !== false) { // Case-insensitive check for 'example'
161+
if (str_contains($rawDocumentation, '```')) {
162+
$node = $this->markupLanguageParser->parse($blockContext->getDocumentParserContext()->getContext(), $rawDocumentation);
163+
$collectionNode = new CollectionNode($node->getValue());
164+
foreach ($node->getValue() as $node) {
165+
if ($node instanceof ParagraphNode) {
166+
$description[] = $node;
167+
}
168+
if ($node instanceof CodeNode) {
168169
$examples[] = $node;
169-
} else {
170-
$sections[] = $node;
170+
}
171+
}
172+
} else {
173+
$rstContentBlockContext = new BlockContext($blockContext->getDocumentParserContext(), $rawDocumentation, false);
174+
$collectionNode = $this->startingRule->apply($rstContentBlockContext);
175+
foreach ($collectionNode->getValue() as $node) {
176+
if (!$node instanceof SectionNode) {
177+
$description[] = $node;
178+
}
179+
}
180+
foreach ($collectionNode->getValue() as $node) {
181+
if ($node instanceof SectionNode) {
182+
$title = $node->getTitle()->toString();
183+
if (stripos($title, 'example') !== false) { // Case-insensitive check for 'example'
184+
$examples[] = $node;
185+
} else {
186+
$sections[] = $node;
187+
}
171188
}
172189
}
173190
}

0 commit comments

Comments
 (0)