Skip to content

Commit 431bb42

Browse files
committed
Add parser
1 parent bd32621 commit 431bb42

File tree

12 files changed

+194
-11
lines changed

12 files changed

+194
-11
lines changed

src/.gitkeep

Whitespace-only changes.

src/BlockParser.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
namespace Recoded\WordPressBlockParser;
4+
5+
use Generator;
6+
use IteratorAggregate;
7+
use LogicException;
8+
use Recoded\WordPressBlockParser\Blocks\Block;
9+
use Recoded\WordPressBlockParser\Blocks\SelfClosingBlock;
10+
use Recoded\WordPressBlockParser\Tokens\BlockClosing;
11+
use Recoded\WordPressBlockParser\Tokens\BlockOpening;
12+
use Recoded\WordPressBlockParser\Tokens\SelfClosingBlock as SelfClosingBlockToken;
13+
14+
/**
15+
* @implements \IteratorAggregate<int, \Recoded\WordPressBlockParser\Blocks\Block|\Recoded\WordPressBlockParser\Blocks\SelfClosingBlock>
16+
*/
17+
final class BlockParser implements IteratorAggregate
18+
{
19+
private Tokenizer $tokenizer;
20+
21+
private int $stackDepth = 0;
22+
23+
/**
24+
* Create a new BlockParser instance.
25+
*
26+
* @param string $content
27+
* @return void
28+
*/
29+
public function __construct(
30+
public readonly string $content,
31+
) {
32+
$this->tokenizer = Tokenizer::create($content);
33+
}
34+
35+
/**
36+
* Create a new parser from content string.
37+
*
38+
* @param string $content
39+
* @return self
40+
*/
41+
public static function create(string $content): self
42+
{
43+
return new self($content);
44+
}
45+
46+
/**
47+
* Iterate over the blocks.
48+
*
49+
* @return \Generator<int, \Recoded\WordPressBlockParser\Blocks\Block|\Recoded\WordPressBlockParser\Blocks\SelfClosingBlock>
50+
*/
51+
public function getIterator(): Generator
52+
{
53+
$opening = null;
54+
55+
foreach ($this->tokenizer as $token) {
56+
if ($token instanceof SelfClosingBlockToken && $this->stackDepth === 0) {
57+
yield new SelfClosingBlock(
58+
namespace: $token->namespace,
59+
name: $token->name,
60+
attributes: $token->attributes,
61+
);
62+
} elseif ($token instanceof BlockOpening && $this->stackDepth++ === 0) {
63+
$opening = $token;
64+
} elseif ($token instanceof BlockClosing && --$this->stackDepth === 0) {
65+
if ($opening === null || $opening->namespace !== $token->namespace || $opening->name !== $token->name) {
66+
throw new LogicException('Closing token does not correspond with opening');
67+
}
68+
69+
$openedAt = $opening->startsAt + $opening->length;
70+
71+
yield new Block(
72+
namespace: $opening->namespace,
73+
name: $opening->name,
74+
attributes: $opening->attributes,
75+
content: substr(
76+
$this->content,
77+
$openedAt,
78+
$token->startsAt - $openedAt,
79+
),
80+
);
81+
}
82+
}
83+
}
84+
}

src/Blocks/Block.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Recoded\WordPressBlockParser\Blocks;
4+
5+
final class Block
6+
{
7+
/**
8+
* Create new Block instance.
9+
*
10+
* @param string $namespace
11+
* @param string $name
12+
* @param array<string, mixed> $attributes
13+
* @param string $content
14+
* @return void
15+
*/
16+
public function __construct(
17+
public readonly string $namespace,
18+
public readonly string $name,
19+
public readonly array $attributes,
20+
public readonly string $content,
21+
) {
22+
//
23+
}
24+
}

src/Blocks/SelfClosingBlock.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Recoded\WordPressBlockParser\Blocks;
4+
5+
final class SelfClosingBlock
6+
{
7+
/**
8+
* Create new SelfClosingBlock instance.
9+
*
10+
* @param string $namespace
11+
* @param string $name
12+
* @param array<string, mixed> $attributes
13+
* @return void
14+
*/
15+
public function __construct(
16+
public readonly string $namespace,
17+
public readonly string $name,
18+
public readonly array $attributes,
19+
) {
20+
//
21+
}
22+
}

src/Tokenizer.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
use Generator;
66
use IteratorAggregate;
7-
use Recoded\WordPressBlockParser\Value\BlockClosing;
8-
use Recoded\WordPressBlockParser\Value\BlockOpening;
9-
use Recoded\WordPressBlockParser\Value\SelfClosingBlock;
7+
use Recoded\WordPressBlockParser\Tokens\BlockClosing;
8+
use Recoded\WordPressBlockParser\Tokens\BlockOpening;
9+
use Recoded\WordPressBlockParser\Tokens\SelfClosingBlock;
1010

1111
/**
12-
* @implements \IteratorAggregate<int, \Recoded\WordPressBlockParser\Value\Token>
12+
* @implements \IteratorAggregate<int, \Recoded\WordPressBlockParser\Tokens\Token>
1313
*/
1414
final class Tokenizer implements IteratorAggregate
1515
{

src/Value/BlockClosing.php renamed to src/Tokens/BlockClosing.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Recoded\WordPressBlockParser\Value;
3+
namespace Recoded\WordPressBlockParser\Tokens;
44

55
final class BlockClosing extends Token
66
{

src/Value/BlockOpening.php renamed to src/Tokens/BlockOpening.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Recoded\WordPressBlockParser\Value;
3+
namespace Recoded\WordPressBlockParser\Tokens;
44

55
final class BlockOpening extends Token
66
{

src/Value/SelfClosingBlock.php renamed to src/Tokens/SelfClosingBlock.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Recoded\WordPressBlockParser\Value;
3+
namespace Recoded\WordPressBlockParser\Tokens;
44

55
final class SelfClosingBlock extends Token
66
{

src/Value/Token.php renamed to src/Tokens/Token.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Recoded\WordPressBlockParser\Value;
3+
namespace Recoded\WordPressBlockParser\Tokens;
44

55
abstract class Token
66
{

tests/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)