Skip to content

Commit bafb537

Browse files
committed
Render tables to rst
1 parent 38247d4 commit bafb537

File tree

4 files changed

+133
-41
lines changed

4 files changed

+133
-41
lines changed

packages/guides-theme-rst/resources/config/guides-theme-rst.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
use phpDocumentor\Guides\RstTheme\Twig\RstExtension;
77
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
88

9+
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
10+
911
return static function (ContainerConfigurator $container): void {
1012
$container->services()
1113
->defaults()
@@ -29,6 +31,7 @@
2931
)
3032

3133
->set(RstExtension::class)
34+
->arg('$nodeRenderer', service('phpdoc.guides.output_node_renderer'))
3235
->tag('twig.extension')
3336
->autowire();
3437
};
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
{{ renderRstTable(node) }}
2+
{{ renderRstTable(node) | raw }}

packages/guides-theme-rst/src/RstTheme/Twig/RstExtension.php

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@
1313

1414
namespace phpDocumentor\Guides\RstTheme\Twig;
1515

16+
use phpDocumentor\Guides\NodeRenderers\NodeRenderer;
17+
use phpDocumentor\Guides\Nodes\Table\TableColumn;
18+
use phpDocumentor\Guides\Nodes\Table\TableRow;
1619
use phpDocumentor\Guides\Nodes\TableNode;
1720
use phpDocumentor\Guides\Nodes\TitleNode;
21+
use phpDocumentor\Guides\RenderContext;
1822
use phpDocumentor\Guides\RstTheme\Configuration\HeaderSyntax;
1923
use Twig\Extension\AbstractExtension;
2024
use Twig\TwigFilter;
@@ -23,6 +27,9 @@
2327
use function array_map;
2428
use function explode;
2529
use function implode;
30+
use function max;
31+
use function mb_str_pad;
32+
use function mb_strlen;
2633
use function min;
2734
use function preg_replace;
2835
use function rtrim;
@@ -31,12 +38,17 @@
3138

3239
final class RstExtension extends AbstractExtension
3340
{
41+
public function __construct(
42+
private NodeRenderer $nodeRenderer,
43+
) {
44+
}
45+
3446
/** @return TwigFunction[] */
3547
public function getFunctions(): array
3648
{
3749
return [
3850
new TwigFunction('renderRstTitle', $this->renderRstTitle(...), ['is_safe' => ['rst'], 'needs_context' => false]),
39-
new TwigFunction('renderRstTable', $this->renderRstTable(...), ['is_safe' => ['rst'], 'needs_context' => false]),
51+
new TwigFunction('renderRstTable', $this->renderRstTable(...), ['is_safe' => ['rst'], 'needs_context' => true]),
4052
new TwigFunction('renderRstIndent', $this->renderRstIndent(...), ['is_safe' => ['rst'], 'needs_context' => false]),
4153
];
4254
}
@@ -77,23 +89,75 @@ public function renderRstTitle(TitleNode $node, string $content): string
7789

7890
$ret .= $content . "\n" . str_repeat($headerSyntax->delimiter(), strlen($content));
7991

80-
return $ret;
92+
return $ret . "\n";
93+
}
94+
95+
/** @param array{env: RenderContext} $context */
96+
public function renderRstTable(array $context, TableNode $node): string
97+
{
98+
$columnWidths = [];
99+
100+
$this->determineMaxLenght($node->getHeaders(), $context['env'], $columnWidths);
101+
$this->determineMaxLenght($node->getData(), $context['env'], $columnWidths);
102+
103+
$ret = $this->renderTableRowEnd($columnWidths);
104+
$ret .= $this->renderRows($node->getHeaders(), $context['env'], $columnWidths, '=');
105+
$ret .= $this->renderRows($node->getData(), $context['env'], $columnWidths);
106+
107+
return $ret . "\n";
108+
}
109+
110+
private function renderCellContent(RenderContext $env, TableColumn $column): string
111+
{
112+
return implode('', array_map(fn ($node) => $this->nodeRenderer->render($node, $env), $column->getValue()));
113+
}
114+
115+
/**
116+
* @param TableRow[] $rows
117+
* @param int[] &$columnWidths
118+
*/
119+
private function determineMaxLenght(array $rows, RenderContext $env, array &$columnWidths): void
120+
{
121+
foreach ($rows as $row) {
122+
foreach ($row->getColumns() as $index => $column) {
123+
$content = $this->renderCellContent($env, $column);
124+
125+
$columnWidths[$index] = max(mb_strlen($content) + 2, $columnWidths[$index] ?? 0);
126+
}
127+
}
81128
}
82129

83-
public function renderRstTable(TableNode $node): string
130+
/**
131+
* @param TableRow[] $rows
132+
* @param int[] $columnWidths
133+
*/
134+
private function renderRows(array $rows, RenderContext $env, array $columnWidths, string $separator = '-'): string
84135
{
85136
$ret = '';
137+
foreach ($rows as $row) {
138+
$ret .= '|';
139+
foreach ($row->getColumns() as $index => $column) {
140+
$content = $this->renderCellContent($env, $column);
86141

87-
foreach ($node->getHeaders() as $header) {
88-
foreach ($header->getColumns() as $column) {
89-
$ret .= $column->getContent() . ' ';
142+
$ret .= ' ' . mb_str_pad($content, $columnWidths[$index] - 2) . ' |';
90143
}
91-
$ret .= "header \n";
144+
145+
$ret .= "\n" . $this->renderTableRowEnd($columnWidths, $separator);
92146
}
93-
foreach ($node->getData() as $row) {
94-
$ret .= 'row'. "\n";
147+
148+
return $ret;
149+
}
150+
151+
/** @param int[] $columnWidths */
152+
private function renderTableRowEnd(array $columnWidths, string $char = '-'): string
153+
{
154+
$ret = '';
155+
foreach ($columnWidths as $width) {
156+
$ret .= '+' . str_repeat($char, $width);
95157
}
96158

159+
$ret .= '+' . "\n";
160+
97161
return $ret;
98162
}
99163
}
Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,56 @@
1-
====================
2-
Markdown Blockquotes
3-
====================
4-
5-
This is a blockquote. It can span multiple lines.
6-
7-
Blockquotes with Multiple Paragraphs
8-
====================================
9-
10-
Dorothy followed her through many of the beautiful rooms in her castle.
11-
12-
The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood.
13-
14-
Blockquotes with Other Elements
15-
===============================
16-
17-
The quarterly results look great!
18-
19-
* Revenue was off the chart.
20-
* Profits were higher than ever.
21-
22-
*Everything* is going according to **plan**.
23-
24-
Blockquotes Best Practices
25-
==========================
26-
27-
Try to put a blank line before...
28-
29-
This is a blockquote
30-
31-
...and after a blockquote.
1+
===============
2+
Markdown Tables
3+
===============
4+
5+
Simple Table
6+
============
7+
8+
+------------+-----+---------------+
9+
| Name | Age | City |
10+
+============+=====+===============+
11+
| John Doe | 29 | New York |
12+
+------------+-----+---------------+
13+
| Jane Smith | 34 | San Francisco |
14+
+------------+-----+---------------+
15+
| Sam Green | 22 | Boston |
16+
+------------+-----+---------------+
17+
18+
Table 1
19+
=======
20+
21+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
22+
| Method name | Description | Parameters | Default |
23+
+==============================================+===================================================================================================================================================================+=======================================================+============================================================================================+
24+
| `setIcon` | icon file, or existing icon identifier | `string $icon` | `'EXT:container/Resources/Public/Icons/Extension.svg'` |
25+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
26+
| `setBackendTemplate` | Template for backend view | `string $backendTemplate` | `null'` |
27+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
28+
| `setGridTemplate` | Template for grid | `string $gridTemplate` | `'EXT:container/Resources/Private/Templates/Container.html'` |
29+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
30+
| `setGridPartialPaths` / `addGridPartialPath` | Partial root paths for grid | `array $gridPartialPaths` / `string $gridPartialPath` | `['EXT:backend/Resources/Private/Partials/', 'EXT:container/Resources/Private/Partials/']` |
31+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
32+
| `setGridLayoutPaths` | Layout root paths for grid | `array $gridLayoutPaths` | `[]` |
33+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
34+
| `setSaveAndCloseInNewContentElementWizard` | saveAndClose for new content element wizard | `bool $saveAndCloseInNewContentElementWizard` | `true` |
35+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
36+
| `setRegisterInNewContentElementWizard` | register in new content element wizard | `bool $registerInNewContentElementWizard` | `true` |
37+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
38+
| `setGroup` | Custom Group (used as optgroup for CType select, and as tab in New Content Element Wizard). If empty "container" is used as tab and no optgroup in CType is used. | `string $group` | `'container'` |
39+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
40+
| `setDefaultValues` | Default values for the newContentElement.wizardItems | `array $defaultValues` | `[]` |
41+
+----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+--------------------------------------------------------------------------------------------+
42+
43+
Table 2
44+
=======
45+
46+
+-----------------------------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------+-----------+
47+
| Option | Description | Default | Parameter |
48+
+=============================+=========================================================================================================+============================================================+===========+
49+
| `contentId` | id of container to to process | current uid of content element `$cObj->data['uid']` | `?int` |
50+
+-----------------------------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------+-----------+
51+
| `colPos` | colPos of children to to process | empty, all children are processed (as `children_<colPos>`) | `?int` |
52+
+-----------------------------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------+-----------+
53+
| `as` | variable to use for proceesedData (only if `colPos` is set) | `children` | `?string` |
54+
+-----------------------------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------+-----------+
55+
| `skipRenderingChildContent` | do not call `ContentObjectRenderer->render()` for children, (`renderedContent` in child will not exist) | empty | `?int` |
56+
+-----------------------------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------+-----------+

0 commit comments

Comments
 (0)