Skip to content

Commit

Permalink
Allow empty block shortcodes
Browse files Browse the repository at this point in the history
  • Loading branch information
samwilson authored Apr 17, 2023
1 parent 23a28e0 commit 9939b56
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 9 deletions.
2 changes: 2 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

<!-- Include full Unleashed Coding Standard -->
<rule ref="Unleashed">
<!-- These can be included after PHP 7.4 support is dropped. -->
<exclude name="SlevomatCodingStandard.TypeHints.UnionTypeHintFormat.DisallowedShortNullable" />
<exclude name="SlevomatCodingStandard.Exceptions.RequireNonCapturingCatch.NonCapturingCatchRequired" />
</rule>
</ruleset>
11 changes: 10 additions & 1 deletion src/Shortcode.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,16 @@ public function getName(): string
public function loadAttrsFromString(string $string): void
{
$doc = new DOMDocument();
$doc->loadHTML('<body ' . $string . ' />');
try {
$loaded = $doc->loadHTML('<body ' . $string . ' />');
} catch (\Throwable $e) {
return;
}

if (! $loaded) {
return;
}

$body = $doc->getElementsByTagName('body')->item(0);
for ($i = 0; $i < $body->attributes->length; ++$i) {
$attr = $body->attributes->item($i);
Expand Down
7 changes: 5 additions & 2 deletions src/ShortcodeBlockContinueParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ final class ShortcodeBlockContinueParser extends AbstractBlockContinueParser
{
private Shortcode $shortcode;

public function __construct(Shortcode $shortcode)
private bool $isClosed;

public function __construct(Shortcode $shortcode, bool $isClosed)
{
$this->shortcode = $shortcode;
$this->isClosed = $isClosed;
}

public function getBlock(): AbstractBlock
Expand All @@ -31,7 +34,7 @@ public function canHaveLazyContinuationLines(): bool

public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue
{
if ($cursor->getLine() === '}}}') {
if ($this->isClosed || $cursor->getLine() === '}}}') {
return BlockContinue::finished();
}

Expand Down
21 changes: 15 additions & 6 deletions src/ShortcodeBlockStartParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,24 @@ public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserSta
{
$braceCount = 3;
foreach (\array_keys($this->shortcodeHandlers) as $code) {
$pattern = '/^\{{' . $braceCount . '}' . \preg_quote($code) . '([^ ]?)/';
$pattern = '/^\{{' . $braceCount . '}' . \preg_quote($code) . '([^ \}]?)(\}{' . $braceCount . '})?/';
$opening = $cursor->match($pattern);
if ($opening !== null) {
$shortcode = new Shortcode($code);
$shortcode->loadAttrsFromString(\substr($cursor->getLine(), \strlen($code) + $braceCount));
$startParser = new ShortcodeBlockContinueParser($shortcode);
if ($opening === null) {
continue;
}

return BlockStart::of($startParser)->at($cursor);
$shortcode = new Shortcode($code);
// If the block is closed on the same line as the attributes, strip the trailing braces.
$attrsString = \substr($cursor->getLine(), \strlen($code) + $braceCount);
$isClosed = \substr($attrsString, -$braceCount) === '}}}';
if ($isClosed) {
$attrsString = \substr($attrsString, 0, -$braceCount);
}

$shortcode->loadAttrsFromString($attrsString);
$startParser = new ShortcodeBlockContinueParser($shortcode, $isClosed);

return BlockStart::of($startParser)->at($cursor);
}

return BlockStart::none();
Expand Down
18 changes: 18 additions & 0 deletions tests/ShortcodeExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,24 @@ public function provideBasics(): array
],
'output' => "<p>Foo</p>\n[\nbody here]\n<p>baz</p>\n",
],
'block on one line with no attrs' => [
'markdown' => "Foo\n\n{{{bar}}}\n\nbaz",
'shortcodes' => [
'bar' => static function (Shortcode $sc) {
return 'TEST';
},
],
'output' => "<p>Foo</p>\nTEST\n<p>baz</p>\n",
],
'block on one line with attrs' => [
'markdown' => "Foo\n\n{{{bar lorem='ip sum'}}}\n\nbaz",
'shortcodes' => [
'bar' => static function (Shortcode $sc) {
return $sc->getAttr('lorem');
},
],
'output' => "<p>Foo</p>\nip sum\n<p>baz</p>\n",
],
];
}
}

0 comments on commit 9939b56

Please sign in to comment.