Skip to content

Commit f8c6cf3

Browse files
authored
Merge pull request #1182 from phpDocumentor/backport/1.x/pr-1179
[1.x] Merge pull request #1179 from phpDocumentor/feature/tables-to-rst
2 parents 119cf24 + 946a8e5 commit f8c6cf3

File tree

11 files changed

+203
-2
lines changed

11 files changed

+203
-2
lines changed

.github/workflows/integrate.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
uses: "phpDocumentor/.github/.github/workflows/[email protected]"
1818
with:
1919
php-version: "8.2"
20+
php-extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, iconv"
2021

2122
coding-standards:
2223
name: "Coding Standards"
@@ -29,6 +30,7 @@ jobs:
2930
uses: "shivammathur/setup-php@v2"
3031
with:
3132
coverage: "none"
33+
extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, iconv"
3234
php-version: "8.2"
3335
tools: "cs2pr"
3436

@@ -45,6 +47,7 @@ jobs:
4547
uses: "phpDocumentor/.github/.github/workflows/lint.yml@main"
4648
with:
4749
composer-options: "--no-check-publish --ansi"
50+
php-extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, iconv"
4851
php-version: "8.2"
4952

5053
static-analysis:
@@ -53,6 +56,7 @@ jobs:
5356
with:
5457
php-version: "8.2"
5558
composer-root-version: "1.x-dev"
59+
php-extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, iconv"
5660

5761
architecture:
5862
name: "Check architecture"
@@ -64,6 +68,7 @@ jobs:
6468
with:
6569
coverage: "none"
6670
php-version: "8.2"
71+
extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, iconv"
6772

6873
- name: "Install dependencies with Composer"
6974
uses: "ramsey/composer-install@v3"
@@ -79,6 +84,7 @@ jobs:
7984
uses: "phpDocumentor/.github/.github/workflows/[email protected]"
8085
with:
8186
composer-root-version: "1.x-dev"
87+
php-extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, iconv"
8288

8389
functional-tests:
8490
name: "Functional test"
@@ -87,6 +93,7 @@ jobs:
8793
with:
8894
test-suite: "functional"
8995
composer-root-version: "1.x-dev"
96+
php-extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, iconv"
9097

9198
integration-tests:
9299
name: "integration test"
@@ -95,6 +102,7 @@ jobs:
95102
with:
96103
test-suite: "integration"
97104
composer-root-version: "1.x-dev"
105+
php-extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, iconv"
98106

99107
xml-lint:
100108
runs-on: "ubuntu-latest"

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
},
3535
"require": {
3636
"php": "^8.1",
37+
"ext-iconv": "*",
3738
"ext-json": "*",
3839
"ext-mbstring": "*",
3940
"doctrine/deprecations": "^1.1",

composer.lock

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

packages/guides-theme-rst/composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"minimum-stability": "stable",
2323
"require": {
2424
"php": "^8.1",
25+
"ext-iconv": "*",
2526
"phpdocumentor/guides": "^1.0 || ^2.0"
2627
},
2728
"extra": {

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

+3
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
};
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

+2
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

+83
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
}
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+
+-----------------------------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------+-----------+
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>

0 commit comments

Comments
 (0)