Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for PLAIN BB-Code and CODE=rich #36

Merged
merged 29 commits into from
Jul 17, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
44595cd
had to reset my branch
asccc Jul 11, 2020
2b42b5b
remove unused files in parser-directory after reset
asccc Jul 11, 2020
aed8838
Fix typos/mistakes in code comments
jr-cologne Jul 13, 2020
59244e5
Properly set up phpunit testsuite and extract helper methods to trait
jr-cologne Jul 13, 2020
0ec4dd4
Add phpunit to phan github action
jr-cologne Jul 13, 2020
0f57d54
simplify the parser and make sure text-nodes are buffered
asccc Jul 13, 2020
5387689
stop parsing after unclosed bbcode
asccc Jul 13, 2020
57538a6
fix wording in test
asccc Jul 13, 2020
cbbb93d
fix wording in test #2
asccc Jul 13, 2020
741d6ca
add comment about nested bbcodes in test
asccc Jul 13, 2020
e3f7f5e
added parser-helpers trait again
asccc Jul 13, 2020
8e12dd5
used more descriptive variable-names in parser
asccc Jul 13, 2020
94f9f70
used more descriptive variable-names in parser
asccc Jul 13, 2020
78efc44
Merge branch 'parser' of github.com:asccc/code-formatter into parser
asccc Jul 13, 2020
036e423
hide phan progress-bar, because github cannot render it
asccc Jul 13, 2020
706b7a5
(wip) added support for nested code-blocks
asccc Jul 15, 2020
eb85f55
some fixes and adjusted node-export logic
asccc Jul 15, 2020
3ba42f4
tests added
asccc Jul 15, 2020
149a1f3
fix code=rich export issue
asccc Jul 15, 2020
40c2803
small adjustments in architecture + saner api
asccc Jul 15, 2020
17af5c0
test if pr is broken
asccc Jul 15, 2020
2e664b0
yep, pr is broken
asccc Jul 15, 2020
8fadf3d
fix IteratorAggregate usage
asccc Jul 16, 2020
463e608
make tests type-safe
asccc Jul 16, 2020
cfb84cb
added more tests and fixed some associated issues
asccc Jul 16, 2020
516a86d
fix typo in file-path
asccc Jul 16, 2020
37824dc
fixed some typos and added more tests
asccc Jul 16, 2020
79466ef
use expectException in tests
asccc Jul 16, 2020
490321b
Merge branch 'parser' of https://github.com/asccc/code-formatter into…
jr-cologne Jul 16, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 47 additions & 21 deletions app/CodeFormatterApp.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
namespace DevCommunityDE\CodeFormatter;

use DevCommunityDE\CodeFormatter\CodeFormatter\CodeFormatter;
use DevCommunityDE\CodeFormatter\Parser\ElemNode;
use DevCommunityDE\CodeFormatter\Parser\Node;
use DevCommunityDE\CodeFormatter\Parser\Parser;
use DevCommunityDE\CodeFormatter\Parser\PregParser;
use DevCommunityDE\CodeFormatter\Parser\Token;
use DevCommunityDE\CodeFormatter\Parser\TextNode;

/**
* Class CodeFormatterApp.
Expand All @@ -22,7 +23,7 @@ class CodeFormatterApp
*/
public function __construct(Parser $parser = null)
{
$this->parser = $parser ?? new PregParser();
$this->parser = $parser ?? new Parser();
}

/**
Expand All @@ -32,17 +33,17 @@ public function __construct(Parser $parser = null)
*/
public function run()
{
$tokens = $this->parseInput();
$nodes = $this->parseInput();

foreach ($tokens as $token) {
echo $this->formatToken($token);
foreach ($nodes as $node) {
echo $this->formatNode($node);
}
}

/**
* parses the code from stdin.
*
* @return iterable<Token>
* @return iterable<Node>
*/
private function parseInput(): iterable
{
Expand All @@ -52,39 +53,64 @@ private function parseInput(): iterable
/**
* formats a token based on its type and language.
jr-cologne marked this conversation as resolved.
Show resolved Hide resolved
*
* @param Token $token
* @param Node $node
*
* @return string
*/
private function formatToken(Token $token): string
private function formatNode(Node $node): string
{
if ($token->isText()) {
return $token->getBody();
if ($node instanceof TextNode) {
return $node->getBody();
}

$language = $token->getAttribute('lang');
\assert(null !== $language);
\assert($node instanceof ElemNode);

if (!$node->isCode()) {
// export node as-is (PLAIN bbcode)
return $this->exportNode($node, null);
}

$language = $this->detectLang($node);
$formatter = CodeFormatter::create($language);
if (null === $formatter) {
// no formatter found, return token as is
return $this->exportToken($token, null);
// no formatter found, return node as is
return $this->exportNode($node, null);
}

$result = $formatter->exec($node->getBody());
return $this->exportNode($node, $result);
}

/**
* detect a code-language form the given node.
*
* @param ElemNode $node
*
* @return string
*/
private function detectLang(ElemNode $node): string
{
$value = $node->getAttr('lang');

if (empty($value)) {
// check if a immediate value is set
// (this is the [code=lang] notation)
$value = $node->getAttr('@value');
}

$result = $formatter->exec($token->getBody());
return $this->exportToken($token, $result);
return $value ?: 'text';
}

/**
* exports a token.
* exports a node.
*
* @param Token $token
* @param Node $node
* @param string|null $body
*
* @return string
*/
private function exportToken(Token $token, ?string $body): string
private function exportNode(Node $node, ?string $body): string
{
return $this->parser->exportToken($token, $body);
return $this->parser->exportNode($node, $body);
}
}
73 changes: 73 additions & 0 deletions app/Parser/ElemAttrs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);
namespace DevCommunityDE\CodeFormatter\Parser;

/**
* this class represents element attributes in a
* raw (match) and a tokenized (pairs) form.
*
* @internal
*/
final class ElemAttrs
{
/** @var string */
private $match;

/** @var array */
private $pairs;

/**
* constructor.
*
* @param string $match
* @param array<string,string> $pairs
*/
public function __construct(string $match, array $pairs)
{
$this->match = $match;
$this->pairs = $pairs;
}

/**
* returns a value.
*
* @param string $name
*
* @return string|null
*/
public function getValue(string $name): ?string
{
return $this->pairs[$name] ?? null;
}

/**
* returns the matched attribute string.
*
* @return string
*/
public function getMatch(): string
{
return $this->match;
}

/**
* checks if some attributes are set.
*
* @return bool
*/
public function hasMatch(): bool
{
return !empty($this->match);
}

/**
* returns the matched attributes as string.
*
* @return string
*/
public function __toString(): string
{
return $this->match;
}
}
72 changes: 72 additions & 0 deletions app/Parser/ElemNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);
namespace DevCommunityDE\CodeFormatter\Parser;

/**
* this class represents a bbcode.
*/
final class ElemNode extends Node
{
/** @var string */
private $name;

/** @var ElemAttrs */
private $attrs;

/**
* constructs a new code-token.
*
* @param string $name
* @param ElemAttrs $attrs
* @param string $body
*/
public function __construct(string $name, ElemAttrs $attrs, string $body)
{
parent::__construct(Node::KIND_ELEM, $body);
$this->name = $name;
$this->attrs = $attrs;
}

/**
* checks if this node represents a [CODE] bbcode.
*
* @return bool
*/
public function isCode(): bool
{
return !strcasecmp($this->name, 'code');
}

/**
* returns the element name.
*
* @return string
*/
public function getName(): string
{
return $this->name;
}

/**
* returns the node attributes.
*
* @return ElemAttrs
*/
public function getAttrs(): ElemAttrs
{
return $this->attrs;
}

/**
* returns a single node attribute.
*
* @param string $name
*
* @return string|null
*/
public function getAttr(string $name): ?string
{
return $this->attrs->getValue($name);
}
}
52 changes: 52 additions & 0 deletions app/Parser/Node.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace DevCommunityDE\CodeFormatter\Parser;

abstract class Node
{
/** text node */
public const KIND_TEXT = 1;

/** element node (bbcode) */
public const KIND_ELEM = 2;

/** @var int */
private $kind;

/** @var string */
private $body;

/**
* constructs a new token.
*
* @param int $kind
* @param string $body
*/
public function __construct(int $kind, string $body)
{
$this->kind = $kind;
$this->body = $body;
}

/**
* @see Token::getKind()
*
* @return int
*/
public function getKind(): int
{
return $this->kind;
}

/**
* @see Token::getBody()
*
* @return string
*/
public function getBody(): string
{
return $this->body;
}
}
Loading