Uploaded From CV. Swandhana Server

This commit is contained in:
Duidev Software House
2025-01-27 08:16:55 +07:00
commit 6b3be42361
15186 changed files with 2328862 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Node\Block\AbstractBlock;
final class Table extends AbstractBlock
{
}
@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Node\Block\AbstractBlock;
final class TableCell extends AbstractBlock
{
public const TYPE_HEADER = 'header';
public const TYPE_DATA = 'data';
public const ALIGN_LEFT = 'left';
public const ALIGN_RIGHT = 'right';
public const ALIGN_CENTER = 'center';
/**
* @psalm-var self::TYPE_*
* @phpstan-var self::TYPE_*
*
* @psalm-readonly-allow-private-mutation
*/
private string $type = self::TYPE_DATA;
/**
* @psalm-var self::ALIGN_*|null
* @phpstan-var self::ALIGN_*|null
*
* @psalm-readonly-allow-private-mutation
*/
private ?string $align = null;
/**
* @psalm-param self::TYPE_* $type
* @psalm-param self::ALIGN_*|null $align
*
* @phpstan-param self::TYPE_* $type
* @phpstan-param self::ALIGN_*|null $align
*/
public function __construct(string $type = self::TYPE_DATA, ?string $align = null)
{
parent::__construct();
$this->type = $type;
$this->align = $align;
}
/**
* @psalm-return self::TYPE_*
*
* @phpstan-return self::TYPE_*
*/
public function getType(): string
{
return $this->type;
}
/**
* @psalm-param self::TYPE_* $type
*
* @phpstan-param self::TYPE_* $type
*/
public function setType(string $type): void
{
$this->type = $type;
}
/**
* @psalm-return self::ALIGN_*|null
*
* @phpstan-return self::ALIGN_*|null
*/
public function getAlign(): ?string
{
return $this->align;
}
/**
* @psalm-param self::ALIGN_*|null $align
*
* @phpstan-param self::ALIGN_*|null $align
*/
public function setAlign(?string $align): void
{
$this->align = $align;
}
}
@@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Extension\Attributes\Util\AttributesHelper;
use League\CommonMark\Node\Node;
use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Renderer\NodeRendererInterface;
use League\CommonMark\Util\HtmlElement;
use League\CommonMark\Xml\XmlNodeRendererInterface;
final class TableCellRenderer implements NodeRendererInterface, XmlNodeRendererInterface
{
private const DEFAULT_ATTRIBUTES = [
TableCell::ALIGN_LEFT => ['align' => 'left'],
TableCell::ALIGN_CENTER => ['align' => 'center'],
TableCell::ALIGN_RIGHT => ['align' => 'right'],
];
/** @var array<TableCell::ALIGN_*, array<string, string|string[]|bool>> */
private array $alignmentAttributes;
/**
* @param array<TableCell::ALIGN_*, array<string, string|string[]|bool>> $alignmentAttributes
*/
public function __construct(array $alignmentAttributes = self::DEFAULT_ATTRIBUTES)
{
$this->alignmentAttributes = $alignmentAttributes;
}
/**
* @param TableCell $node
*
* {@inheritDoc}
*
* @psalm-suppress MoreSpecificImplementedParamType
*/
public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable
{
TableCell::assertInstanceOf($node);
$attrs = $node->data->get('attributes');
if (($alignment = $node->getAlign()) !== null) {
$attrs = AttributesHelper::mergeAttributes($attrs, $this->alignmentAttributes[$alignment]);
}
$tag = $node->getType() === TableCell::TYPE_HEADER ? 'th' : 'td';
return new HtmlElement($tag, $attrs, $childRenderer->renderNodes($node->children()));
}
public function getXmlTagName(Node $node): string
{
return 'table_cell';
}
/**
* @param TableCell $node
*
* @return array<string, scalar>
*
* @psalm-suppress MoreSpecificImplementedParamType
*/
public function getXmlAttributes(Node $node): array
{
TableCell::assertInstanceOf($node);
$ret = ['type' => $node->getType()];
if (($align = $node->getAlign()) !== null) {
$ret['align'] = $align;
}
return $ret;
}
}
@@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Environment\EnvironmentBuilderInterface;
use League\CommonMark\Extension\ConfigurableExtensionInterface;
use League\CommonMark\Renderer\HtmlDecorator;
use League\Config\ConfigurationBuilderInterface;
use Nette\Schema\Expect;
final class TableExtension implements ConfigurableExtensionInterface
{
public function configureSchema(ConfigurationBuilderInterface $builder): void
{
$attributeArraySchema = Expect::arrayOf(
Expect::type('string|string[]|bool'), // attribute value(s)
'string' // attribute name
)->mergeDefaults(false);
$builder->addSchema('table', Expect::structure([
'wrap' => Expect::structure([
'enabled' => Expect::bool()->default(false),
'tag' => Expect::string()->default('div'),
'attributes' => Expect::arrayOf(Expect::string()),
]),
'alignment_attributes' => Expect::structure([
'left' => (clone $attributeArraySchema)->default(['align' => 'left']),
'center' => (clone $attributeArraySchema)->default(['align' => 'center']),
'right' => (clone $attributeArraySchema)->default(['align' => 'right']),
]),
]));
}
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, $tableRenderer)
->addRenderer(TableSection::class, new TableSectionRenderer())
->addRenderer(TableRow::class, new TableRowRenderer())
->addRenderer(TableCell::class, new TableCellRenderer($environment->getConfiguration()->get('table/alignment_attributes')));
}
}
@@ -0,0 +1,200 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Parser\Block\AbstractBlockContinueParser;
use League\CommonMark\Parser\Block\BlockContinue;
use League\CommonMark\Parser\Block\BlockContinueParserInterface;
use League\CommonMark\Parser\Block\BlockContinueParserWithInlinesInterface;
use League\CommonMark\Parser\Cursor;
use League\CommonMark\Parser\InlineParserEngineInterface;
use League\CommonMark\Util\ArrayCollection;
final class TableParser extends AbstractBlockContinueParser implements BlockContinueParserWithInlinesInterface
{
/** @psalm-readonly */
private Table $block;
/**
* @var ArrayCollection<string>
*
* @psalm-readonly-allow-private-mutation
*/
private ArrayCollection $bodyLines;
/**
* @var array<int, string|null>
* @psalm-var array<int, TableCell::ALIGN_*|null>
* @phpstan-var array<int, TableCell::ALIGN_*|null>
*
* @psalm-readonly
*/
private array $columns;
/**
* @var array<int, string>
*
* @psalm-readonly-allow-private-mutation
*/
private array $headerCells;
/** @psalm-readonly-allow-private-mutation */
private bool $nextIsSeparatorLine = true;
/**
* @param array<int, string|null> $columns
* @param array<int, string> $headerCells
*
* @psalm-param array<int, TableCell::ALIGN_*|null> $columns
*
* @phpstan-param array<int, TableCell::ALIGN_*|null> $columns
*/
public function __construct(array $columns, array $headerCells)
{
$this->block = new Table();
$this->bodyLines = new ArrayCollection();
$this->columns = $columns;
$this->headerCells = $headerCells;
}
public function canHaveLazyContinuationLines(): bool
{
return true;
}
public function getBlock(): Table
{
return $this->block;
}
public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue
{
if (\strpos($cursor->getLine(), '|') === false) {
return BlockContinue::none();
}
return BlockContinue::at($cursor);
}
public function addLine(string $line): void
{
if ($this->nextIsSeparatorLine) {
$this->nextIsSeparatorLine = false;
} else {
$this->bodyLines[] = $line;
}
}
public function parseInlines(InlineParserEngineInterface $inlineParser): void
{
$headerColumns = \count($this->headerCells);
$head = new TableSection(TableSection::TYPE_HEAD);
$this->block->appendChild($head);
$headerRow = new TableRow();
$head->appendChild($headerRow);
for ($i = 0; $i < $headerColumns; $i++) {
$cell = $this->headerCells[$i];
$tableCell = $this->parseCell($cell, $i, $inlineParser);
$tableCell->setType(TableCell::TYPE_HEADER);
$headerRow->appendChild($tableCell);
}
$body = null;
foreach ($this->bodyLines as $rowLine) {
$cells = self::split($rowLine);
$row = new TableRow();
// Body can not have more columns than head
for ($i = 0; $i < $headerColumns; $i++) {
$cell = $cells[$i] ?? '';
$tableCell = $this->parseCell($cell, $i, $inlineParser);
$row->appendChild($tableCell);
}
if ($body === null) {
// It's valid to have a table without body. In that case, don't add an empty TableBody node.
$body = new TableSection();
$this->block->appendChild($body);
}
$body->appendChild($row);
}
}
private function parseCell(string $cell, int $column, InlineParserEngineInterface $inlineParser): TableCell
{
$tableCell = new TableCell();
if ($column < \count($this->columns)) {
$tableCell->setAlign($this->columns[$column]);
}
$inlineParser->parse(\trim($cell), $tableCell);
return $tableCell;
}
/**
* @internal
*
* @return array<int, string>
*/
public static function split(string $line): array
{
$cursor = new Cursor(\trim($line));
if ($cursor->getCurrentCharacter() === '|') {
$cursor->advanceBy(1);
}
$cells = [];
$sb = '';
while (! $cursor->isAtEnd()) {
switch ($c = $cursor->getCurrentCharacter()) {
case '\\':
if ($cursor->peek() === '|') {
// Pipe is special for table parsing. An escaped pipe doesn't result in a new cell, but is
// passed down to inline parsing as an unescaped pipe. Note that that applies even for the `\|`
// in an input like `\\|` - in other words, table parsing doesn't support escaping backslashes.
$sb .= '|';
$cursor->advanceBy(1);
} else {
// Preserve backslash before other characters or at end of line.
$sb .= '\\';
}
break;
case '|':
$cells[] = $sb;
$sb = '';
break;
default:
$sb .= $c;
}
$cursor->advanceBy(1);
}
if ($sb !== '') {
$cells[] = $sb;
}
return $cells;
}
}
@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Node\Node;
use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Renderer\NodeRendererInterface;
use League\CommonMark\Util\HtmlElement;
use League\CommonMark\Xml\XmlNodeRendererInterface;
final class TableRenderer implements NodeRendererInterface, XmlNodeRendererInterface
{
/**
* @param Table $node
*
* {@inheritDoc}
*
* @psalm-suppress MoreSpecificImplementedParamType
*/
public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable
{
Table::assertInstanceOf($node);
$attrs = $node->data->get('attributes');
$separator = $childRenderer->getInnerSeparator();
$children = $childRenderer->renderNodes($node->children());
return new HtmlElement('table', $attrs, $separator . \trim($children) . $separator);
}
public function getXmlTagName(Node $node): string
{
return 'table';
}
/**
* {@inheritDoc}
*/
public function getXmlAttributes(Node $node): array
{
return [];
}
}
@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Node\Block\AbstractBlock;
final class TableRow extends AbstractBlock
{
}
@@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Node\Node;
use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Renderer\NodeRendererInterface;
use League\CommonMark\Util\HtmlElement;
use League\CommonMark\Xml\XmlNodeRendererInterface;
final class TableRowRenderer implements NodeRendererInterface, XmlNodeRendererInterface
{
/**
* @param TableRow $node
*
* {@inheritDoc}
*
* @psalm-suppress MoreSpecificImplementedParamType
*/
public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable
{
TableRow::assertInstanceOf($node);
$attrs = $node->data->get('attributes');
$separator = $childRenderer->getInnerSeparator();
return new HtmlElement('tr', $attrs, $separator . $childRenderer->renderNodes($node->children()) . $separator);
}
public function getXmlTagName(Node $node): string
{
return 'table_row';
}
/**
* {@inheritDoc}
*/
public function getXmlAttributes(Node $node): array
{
return [];
}
}
@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Node\Block\AbstractBlock;
final class TableSection extends AbstractBlock
{
public const TYPE_HEAD = 'head';
public const TYPE_BODY = 'body';
/**
* @psalm-var self::TYPE_*
* @phpstan-var self::TYPE_*
*
* @psalm-readonly
*/
private string $type;
/**
* @psalm-param self::TYPE_* $type
*
* @phpstan-param self::TYPE_* $type
*/
public function __construct(string $type = self::TYPE_BODY)
{
parent::__construct();
$this->type = $type;
}
/**
* @psalm-return self::TYPE_*
*
* @phpstan-return self::TYPE_*
*/
public function getType(): string
{
return $this->type;
}
public function isHead(): bool
{
return $this->type === self::TYPE_HEAD;
}
public function isBody(): bool
{
return $this->type === self::TYPE_BODY;
}
}
@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Node\Node;
use League\CommonMark\Renderer\ChildNodeRendererInterface;
use League\CommonMark\Renderer\NodeRendererInterface;
use League\CommonMark\Util\HtmlElement;
use League\CommonMark\Xml\XmlNodeRendererInterface;
final class TableSectionRenderer implements NodeRendererInterface, XmlNodeRendererInterface
{
/**
* @param TableSection $node
*
* {@inheritDoc}
*
* @psalm-suppress MoreSpecificImplementedParamType
*/
public function render(Node $node, ChildNodeRendererInterface $childRenderer)
{
TableSection::assertInstanceOf($node);
if (! $node->hasChildren()) {
return '';
}
$attrs = $node->data->get('attributes');
$separator = $childRenderer->getInnerSeparator();
$tag = $node->getType() === TableSection::TYPE_HEAD ? 'thead' : 'tbody';
return new HtmlElement($tag, $attrs, $separator . $childRenderer->renderNodes($node->children()) . $separator);
}
public function getXmlTagName(Node $node): string
{
return 'table_section';
}
/**
* @param TableSection $node
*
* @return array<string, scalar>
*
* @psalm-suppress MoreSpecificImplementedParamType
*/
public function getXmlAttributes(Node $node): array
{
TableSection::assertInstanceOf($node);
return [
'type' => $node->getType(),
];
}
}
@@ -0,0 +1,158 @@
<?php
declare(strict_types=1);
/*
* This is part of the league/commonmark package.
*
* (c) Martin Hasoň <[email protected]>
* (c) Webuni s.r.o. <[email protected]>
* (c) Colin O'Dell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Extension\Table;
use League\CommonMark\Parser\Block\BlockStart;
use League\CommonMark\Parser\Block\BlockStartParserInterface;
use League\CommonMark\Parser\Block\ParagraphParser;
use League\CommonMark\Parser\Cursor;
use League\CommonMark\Parser\MarkdownParserStateInterface;
final class TableStartParser implements BlockStartParserInterface
{
public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart
{
$paragraph = $parserState->getParagraphContent();
if ($paragraph === null || \strpos($paragraph, '|') === false) {
return BlockStart::none();
}
$columns = self::parseSeparator($cursor);
if (\count($columns) === 0) {
return BlockStart::none();
}
$lines = \explode("\n", $paragraph);
$lastLine = \array_pop($lines);
$headerCells = TableParser::split($lastLine);
if (\count($headerCells) > \count($columns)) {
return BlockStart::none();
}
$cursor->advanceToEnd();
$parsers = [];
if (\count($lines) > 0) {
$p = new ParagraphParser();
$p->addLine(\implode("\n", $lines));
$parsers[] = $p;
}
$parsers[] = new TableParser($columns, $headerCells);
return BlockStart::of(...$parsers)
->at($cursor)
->replaceActiveBlockParser();
}
/**
* @return array<int, string|null>
*
* @psalm-return array<int, TableCell::ALIGN_*|null>
*
* @phpstan-return array<int, TableCell::ALIGN_*|null>
*/
private static function parseSeparator(Cursor $cursor): array
{
$columns = [];
$pipes = 0;
$valid = false;
while (! $cursor->isAtEnd()) {
switch ($c = $cursor->getCurrentCharacter()) {
case '|':
$cursor->advanceBy(1);
$pipes++;
if ($pipes > 1) {
// More than one adjacent pipe not allowed
return [];
}
// Need at least one pipe, even for a one-column table
$valid = true;
break;
case '-':
case ':':
if ($pipes === 0 && \count($columns) > 0) {
// Need a pipe after the first column (first column doesn't need to start with one)
return [];
}
$left = false;
$right = false;
if ($c === ':') {
$left = true;
$cursor->advanceBy(1);
}
if ($cursor->match('/^-+/') === null) {
// Need at least one dash
return [];
}
if ($cursor->getCurrentCharacter() === ':') {
$right = true;
$cursor->advanceBy(1);
}
$columns[] = self::getAlignment($left, $right);
// Next, need another pipe
$pipes = 0;
break;
case ' ':
case "\t":
// White space is allowed between pipes and columns
$cursor->advanceToNextNonSpaceOrTab();
break;
default:
// Any other character is invalid
return [];
}
}
if (! $valid) {
return [];
}
return $columns;
}
/**
* @psalm-return TableCell::ALIGN_*|null
*
* @phpstan-return TableCell::ALIGN_*|null
*
* @psalm-pure
*/
private static function getAlignment(bool $left, bool $right): ?string
{
if ($left && $right) {
return TableCell::ALIGN_CENTER;
}
if ($left) {
return TableCell::ALIGN_LEFT;
}
if ($right) {
return TableCell::ALIGN_RIGHT;
}
return null;
}
}