Skip to content

Commit 668f7e1

Browse files
linawolfjaapio
authored andcommitted
[FEATURE] Render tables to rst
1 parent 4f6a949 commit 668f7e1

File tree

7 files changed

+189
-0
lines changed

7 files changed

+189
-0
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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
{{ renderRstTable(node) | raw }}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
use phpDocumentor\Guides\Nodes\QuoteNode;
5252
use phpDocumentor\Guides\Nodes\SectionNode;
5353
use phpDocumentor\Guides\Nodes\SeparatorNode;
54+
use phpDocumentor\Guides\Nodes\TableNode;
5455
use phpDocumentor\Guides\Nodes\TitleNode;
5556

5657
return [
@@ -74,6 +75,7 @@
7475
CitationNode::class => 'body/citation.rst.twig',
7576
FootnoteNode::class => 'body/footnote.rst.twig',
7677
AnnotationListNode::class => 'body/annotation-list.rst.twig',
78+
TableNode::class => 'body/table.rst.twig',
7779
// Inline
7880
ImageInlineNode::class => 'inline/image.rst.twig',
7981
AbbreviationInlineNode::class => 'inline/textroles/abbreviation.rst.twig',

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

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +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;
19+
use phpDocumentor\Guides\Nodes\TableNode;
1620
use phpDocumentor\Guides\Nodes\TitleNode;
21+
use phpDocumentor\Guides\RenderContext;
1722
use phpDocumentor\Guides\RstTheme\Configuration\HeaderSyntax;
1823
use Twig\Extension\AbstractExtension;
1924
use Twig\TwigFilter;
@@ -22,6 +27,9 @@
2227
use function array_map;
2328
use function explode;
2429
use function implode;
30+
use function max;
31+
use function mb_str_pad;
32+
use function mb_strlen;
2533
use function min;
2634
use function preg_replace;
2735
use function rtrim;
@@ -30,11 +38,17 @@
3038

3139
final class RstExtension extends AbstractExtension
3240
{
41+
public function __construct(
42+
private NodeRenderer $nodeRenderer,
43+
) {
44+
}
45+
3346
/** @return TwigFunction[] */
3447
public function getFunctions(): array
3548
{
3649
return [
3750
new TwigFunction('renderRstTitle', $this->renderRstTitle(...), ['is_safe' => ['rst'], 'needs_context' => false]),
51+
new TwigFunction('renderRstTable', $this->renderRstTable(...), ['is_safe' => ['rst'], 'needs_context' => true]),
3852
new TwigFunction('renderRstIndent', $this->renderRstIndent(...), ['is_safe' => ['rst'], 'needs_context' => false]),
3953
];
4054
}
@@ -75,6 +89,75 @@ public function renderRstTitle(TitleNode $node, string $content): string
7589

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

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+
}
128+
}
129+
130+
/**
131+
* @param TableRow[] $rows
132+
* @param int[] $columnWidths
133+
*/
134+
private function renderRows(array $rows, RenderContext $env, array $columnWidths, string $separator = '-'): string
135+
{
136+
$ret = '';
137+
foreach ($rows as $row) {
138+
$ret .= '|';
139+
foreach ($row->getColumns() as $index => $column) {
140+
$content = $this->renderCellContent($env, $column);
141+
142+
$ret .= ' ' . mb_str_pad($content, $columnWidths[$index] - 2) . ' |';
143+
}
144+
145+
$ret .= "\n" . $this->renderTableRowEnd($columnWidths, $separator);
146+
}
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);
157+
}
158+
159+
$ret .= '+' . "\n";
160+
78161
return $ret;
79162
}
80163
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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+
+-----------------------------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------+-----------+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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 packages/guides-cli/resources/schema/guides.xsd"
5+
input-format="md"
6+
theme="rst"
7+
>
8+
<project title="Project Title" version="6.4"/>
9+
<extension class="phpDocumentor\Guides\RstTheme"/>
10+
<output-format>rst</output-format>
11+
</guides>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Markdown Tables
2+
3+
## Simple Table
4+
5+
| Name | Age | City |
6+
|------------|-----|--------------|
7+
| John Doe | 29 | New York |
8+
| Jane Smith | 34 | San Francisco|
9+
| Sam Green | 22 | Boston |
10+
11+
## Table 1
12+
13+
| Method name | Description | Parameters | Default |
14+
| ----------- | ----------- | ---------- | ---------- |
15+
| `setIcon` | icon file, or existing icon identifier | `string $icon` | `'EXT:container/Resources/Public/Icons/Extension.svg'` |
16+
| `setBackendTemplate` | Template for backend view| `string $backendTemplate` | `null'` |
17+
| `setGridTemplate` | Template for grid | `string $gridTemplate` | `'EXT:container/Resources/Private/Templates/Container.html'` |
18+
| `setGridPartialPaths` / `addGridPartialPath` | Partial root paths for grid | `array $gridPartialPaths` / `string $gridPartialPath` | `['EXT:backend/Resources/Private/Partials/', 'EXT:container/Resources/Private/Partials/']` |
19+
| `setGridLayoutPaths` | Layout root paths for grid | `array $gridLayoutPaths` | `[]` |
20+
| `setSaveAndCloseInNewContentElementWizard` | saveAndClose for new content element wizard | `bool $saveAndCloseInNewContentElementWizard` | `true` |
21+
| `setRegisterInNewContentElementWizard` |register in new content element wizard | `bool $registerInNewContentElementWizard` | `true` |
22+
| `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'` |
23+
| `setDefaultValues` | Default values for the newContentElement.wizardItems | `array $defaultValues` | `[]` |
24+
25+
## Table 2
26+
27+
| Option | Description | Default | Parameter |
28+
|-----------------------------|------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|-------------|
29+
| `contentId` | id of container to to process | current uid of content element ``$cObj->data['uid']`` | ``?int`` |
30+
| `colPos` | colPos of children to to process | empty, all children are processed (as ``children_<colPos>``) | ``?int`` |
31+
| `as` | variable to use for proceesedData (only if ``colPos`` is set) | ``children`` | ``?string`` |
32+
| `skipRenderingChildContent` | do not call ``ContentObjectRenderer->render()`` for children, (``renderedContent`` in child will not exist) | empty | ``?int`` |

0 commit comments

Comments
 (0)