Skip to content

Commit

Permalink
Add config for optionally wrapping tables within a container
Browse files Browse the repository at this point in the history
  • Loading branch information
colinodell committed Jan 22, 2022
1 parent 4cc9dfa commit 01984fa
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 52 deletions.
5 changes: 5 additions & 0 deletions .phpstorm.meta.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@
'slug_normalizer/instance',
'slug_normalizer/max_length',
'slug_normalizer/unique',
'table',
'table/wrap',
'table/wrap/attributes',
'table/wrap/enabled',
'table/wrap/tag',
'table_of_contents',
'table_of_contents/html_class',
'table_of_contents/max_heading_level',
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Updates should follow the [Keep a CHANGELOG](https://keepachangelog.com/) princi
- Added new `ConverterInterface`
- Added new `MarkdownToXmlConverter` class
- Added new `HtmlDecorator` class which can wrap existing renderers with additional HTML tags
- Added new `table/wrap` config to apply an optional wrapping/container element around a table (#780)

### Changed

Expand Down
34 changes: 33 additions & 1 deletion docs/2.2/extensions/tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\MarkdownConverter;

// Define your configuration, if needed
$config = [];
$config = [
'table' => [
'wrap' => [
'enabled' => false,
'tag' => 'div',
'attributes' => [],
],
],
];

// Configure the Environment with all the CommonMark parsers/renderers
$environment = new Environment($config);
Expand Down Expand Up @@ -89,6 +97,30 @@ Result:
| cell 2.1 | cell 2.2 | cell 2.3 |
```

## Configuration

### Wrapping Container

You can "wrap" the table with a container element by configuring the following options:

- `enabled`: (`boolean`) Whether to wrap the table with a container element. Defaults to `false`.
- `tag`: (`string`) The tag name of the container element. Defaults to `div`.
- `attributes`: (`array`) An array of attributes to apply to the container element. Defaults to `[]`.

For example, to wrap all tables within a `<div class="table-responsive">` container element:

```php
$config = [
'table' => [
'wrap' => [
'enabled' => true,
'tag' => 'div',
'attributes' => ['class' => 'table-responsive'],
],
],
];
```

## Credits

The Table functionality was originally built by [Martin Hasoň](https://github.com/hason) and [Webuni s.r.o.](https://www.webuni.cz) before it was merged into the core parser.
25 changes: 22 additions & 3 deletions src/Extension/Table/TableExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,35 @@
namespace League\CommonMark\Extension\Table;

use League\CommonMark\Environment\EnvironmentBuilderInterface;
use League\CommonMark\Extension\ExtensionInterface;
use League\CommonMark\Extension\ConfigurableExtensionInterface;
use League\CommonMark\Renderer\HtmlDecorator;
use League\Config\ConfigurationBuilderInterface;
use Nette\Schema\Expect;

final class TableExtension implements ExtensionInterface
final class TableExtension implements ConfigurableExtensionInterface
{
public function configureSchema(ConfigurationBuilderInterface $builder): void
{
$builder->addSchema('table', Expect::structure([
'wrap' => Expect::structure([
'enabled' => Expect::bool()->default(false),
'tag' => Expect::string()->default('div'),
'attributes' => Expect::arrayOf(Expect::string()),
]),
]));
}

public function register(EnvironmentBuilderInterface $environment): void
{
$tableRenderer = new TableRenderer();
if ($environment->getConfiguration()->get('table/wrap/enabled')) {
$tableRenderer = new HtmlDecorator($tableRenderer, $environment->getConfiguration()->get('table/wrap/tag'), $environment->getConfiguration()->get('table/wrap/attributes'));
}

$environment
->addBlockStartParser(new TableStartParser())

->addRenderer(Table::class, new TableRenderer())
->addRenderer(Table::class, $tableRenderer)
->addRenderer(TableSection::class, new TableSectionRenderer())
->addRenderer(TableRow::class, new TableRowRenderer())
->addRenderer(TableCell::class, new TableCellRenderer());
Expand Down
62 changes: 14 additions & 48 deletions tests/functional/Extension/Table/TableMarkdownTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,69 +15,35 @@

namespace League\CommonMark\Tests\Functional\Extension\Table;

use League\CommonMark\ConverterInterface;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\Parser\MarkdownParser;
use League\CommonMark\Renderer\HtmlRenderer;
use League\CommonMark\Renderer\MarkdownRendererInterface;
use PHPUnit\Framework\TestCase;
use League\CommonMark\MarkdownConverter;
use League\CommonMark\Tests\Functional\AbstractLocalDataTest;

/**
* @internal
*/
final class TableMarkdownTest extends TestCase
final class TableMarkdownTest extends AbstractLocalDataTest
{
private Environment $environment;

private MarkdownParser $parser;

protected function setUp(): void
{
$this->environment = new Environment();
$this->environment->addExtension(new CommonMarkCoreExtension());
$this->environment->addExtension(new TableExtension());

$this->parser = new MarkdownParser($this->environment);
}

/**
* @dataProvider dataProvider
* @param array<string, mixed> $config
*/
public function testRenderer(string $markdown, string $html, string $testName): void
protected function createConverter(array $config = []): ConverterInterface
{
$renderer = new HtmlRenderer($this->environment);
$this->assertCommonMark($renderer, $markdown, $html, $testName);
$environment = new Environment($config);
$environment->addExtension(new CommonMarkCoreExtension());
$environment->addExtension(new TableExtension());

return new MarkdownConverter($environment);
}

/**
* @return array<array<string>>
* {@inheritDoc}
*/
public function dataProvider(): array
public function dataProvider(): iterable
{
$ret = [];
foreach (\glob(__DIR__ . '/md/*.md') as $markdownFile) {
$testName = \basename($markdownFile, '.md');

$markdown = \file_get_contents($markdownFile);
$html = \file_get_contents(__DIR__ . '/md/' . $testName . '.html');

$ret[] = [$markdown, $html, $testName];
}

return $ret;
}

protected function assertCommonMark(MarkdownRendererInterface $renderer, string $markdown, string $html, string $testName): void
{
$documentAST = $this->parser->parse($markdown);
$actualResult = $renderer->renderDocument($documentAST);

$failureMessage = \sprintf('Unexpected result for "%s" test', $testName);
$failureMessage .= "\n=== markdown ===============\n" . $markdown;
$failureMessage .= "\n=== expected ===============\n" . $html;
$failureMessage .= "\n=== got ====================\n" . $actualResult;

$this->assertEquals($html, $actualResult, $failureMessage);
yield from $this->loadTests(__DIR__ . '/md');
}
}
18 changes: 18 additions & 0 deletions tests/functional/Extension/Table/md/wrapped.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div class="table-responsive"><table>
<thead>
<tr>
<th>header 1</th>
<th>header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>cell 1.1</td>
<td>cell 1.2</td>
</tr>
<tr>
<td>cell 2.1</td>
<td>cell 2.2</td>
</tr>
</tbody>
</table></div>
11 changes: 11 additions & 0 deletions tests/functional/Extension/Table/md/wrapped.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
table:
wrap:
enabled: true
attributes: { class: "table-responsive" }
---

header 1 | header 2
-------- | --------
cell 1.1 | cell 1.2
cell 2.1 | cell 2.2

0 comments on commit 01984fa

Please sign in to comment.