mirror of
https://github.com/erusev/parsedown.git
synced 2024-09-19 19:41:29 +02:00
Add HeaderSlug configurable
Adds HeaderSlug configurable, with the option for the slug function to be customised. Co-authored-by: netniV <netniv@hotmail.com>
This commit is contained in:
parent
74df602863
commit
e332b4710a
@ -5,6 +5,7 @@ namespace Erusev\Parsedown\Components\Blocks;
|
||||
use Erusev\Parsedown\AST\Handler;
|
||||
use Erusev\Parsedown\AST\StateRenderable;
|
||||
use Erusev\Parsedown\Components\Block;
|
||||
use Erusev\Parsedown\Configurables\HeaderSlug;
|
||||
use Erusev\Parsedown\Configurables\StrictMode;
|
||||
use Erusev\Parsedown\Html\Renderables\Element;
|
||||
use Erusev\Parsedown\Parsedown;
|
||||
@ -96,9 +97,16 @@ final class Header implements Block
|
||||
return new Handler(
|
||||
/** @return Element */
|
||||
function (State $State) {
|
||||
$HeaderSlug = $State->get(HeaderSlug::class);
|
||||
$attributes = (
|
||||
$HeaderSlug->isEnabled()
|
||||
? ['id' => $HeaderSlug->transform($this->text())]
|
||||
: []
|
||||
);
|
||||
|
||||
return new Element(
|
||||
'h' . \strval($this->level()),
|
||||
[],
|
||||
$attributes,
|
||||
$State->applyTo(Parsedown::line($this->text(), $State))
|
||||
);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use Erusev\Parsedown\AST\Handler;
|
||||
use Erusev\Parsedown\AST\StateRenderable;
|
||||
use Erusev\Parsedown\Components\AcquisitioningBlock;
|
||||
use Erusev\Parsedown\Components\Block;
|
||||
use Erusev\Parsedown\Configurables\HeaderSlug;
|
||||
use Erusev\Parsedown\Html\Renderables\Element;
|
||||
use Erusev\Parsedown\Parsedown;
|
||||
use Erusev\Parsedown\Parsing\Context;
|
||||
@ -88,9 +89,16 @@ final class SetextHeader implements AcquisitioningBlock
|
||||
return new Handler(
|
||||
/** @return Element */
|
||||
function (State $State) {
|
||||
$HeaderSlug = $State->get(HeaderSlug::class);
|
||||
$attributes = (
|
||||
$HeaderSlug->isEnabled()
|
||||
? ['id' => $HeaderSlug->transform($this->text())]
|
||||
: []
|
||||
);
|
||||
|
||||
return new Element(
|
||||
'h' . \strval($this->level()),
|
||||
[],
|
||||
$attributes,
|
||||
$State->applyTo(Parsedown::line($this->text(), $State))
|
||||
);
|
||||
}
|
||||
|
64
src/Configurables/HeaderSlug.php
Normal file
64
src/Configurables/HeaderSlug.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Erusev\Parsedown\Configurables;
|
||||
|
||||
use Erusev\Parsedown\Configurable;
|
||||
|
||||
final class HeaderSlug implements Configurable
|
||||
{
|
||||
/** @var bool */
|
||||
private $enabled = false;
|
||||
|
||||
/** @var \Closure(string):string */
|
||||
private $slugCallback;
|
||||
|
||||
/**
|
||||
* @param bool $enabled
|
||||
* @param (\Closure(string):string)|null $slugCallback
|
||||
*/
|
||||
public function __construct($enabled, $slugCallback = null)
|
||||
{
|
||||
$this->enabled = $enabled;
|
||||
|
||||
if (! isset($slugCallback)) {
|
||||
$this->slugCallback = function (string $text): string {
|
||||
$slug = \mb_strtolower($text);
|
||||
$slug = \str_replace(' ', '-', $slug);
|
||||
$slug = \preg_replace('/[^\p{L}\p{N}\p{M}-]+/u', '', $slug);
|
||||
|
||||
return $slug;
|
||||
};
|
||||
} else {
|
||||
$this->slugCallback = $slugCallback;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return bool */
|
||||
public function isEnabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
public function transform(string $text): string
|
||||
{
|
||||
return ($this->slugCallback)($text);
|
||||
}
|
||||
|
||||
/** @param \Closure(string):string $slugCallback */
|
||||
public static function withCallback($slugCallback): self
|
||||
{
|
||||
return new self(true, $slugCallback);
|
||||
}
|
||||
|
||||
/** @return self */
|
||||
public static function enabled()
|
||||
{
|
||||
return new self(true);
|
||||
}
|
||||
|
||||
/** @return self */
|
||||
public static function initial()
|
||||
{
|
||||
return new self(false);
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ use Erusev\Parsedown\Components\Blocks\Markup as BlockMarkup;
|
||||
use Erusev\Parsedown\Components\Inlines\Markup as InlineMarkup;
|
||||
use Erusev\Parsedown\Configurables\BlockTypes;
|
||||
use Erusev\Parsedown\Configurables\Breaks;
|
||||
use Erusev\Parsedown\Configurables\HeaderSlug;
|
||||
use Erusev\Parsedown\Configurables\InlineTypes;
|
||||
use Erusev\Parsedown\Configurables\SafeMode;
|
||||
use Erusev\Parsedown\Configurables\StrictMode;
|
||||
@ -59,6 +60,7 @@ class ParsedownTest extends TestCase
|
||||
new SafeMode(\substr($test, 0, 3) === 'xss'),
|
||||
new StrictMode(\substr($test, 0, 6) === 'strict'),
|
||||
new Breaks(\substr($test, 0, 14) === 'breaks_enabled'),
|
||||
new HeaderSlug(\substr($test, 0, 4) === 'slug'),
|
||||
]));
|
||||
|
||||
$actualMarkup = $Parsedown->toHtml($markdown);
|
||||
|
10
tests/data/slug_heading.html
Normal file
10
tests/data/slug_heading.html
Normal file
@ -0,0 +1,10 @@
|
||||
<h1 id="foo">foo</h1>
|
||||
<h1 id="foo-bar">foo bar</h1>
|
||||
<h1 id="foobar">foo_bar</h1>
|
||||
<h1 id="foobar">foo+bar</h1>
|
||||
<h1 id="2rer0ගම්මැද්ද-v-force-ඉනොවේශන්-නේෂන්-සඳහා-එවූ-නි">2rer*(0👍ගම්මැද්ද V FORCE ඉනොවේශන් නේෂන් සඳහා එවූ නි</h1>
|
||||
<h2 id="foo">foo</h2>
|
||||
<h2 id="foo-bar">foo bar</h2>
|
||||
<h2 id="foobar">foo_bar</h2>
|
||||
<h2 id="foobar">foo+bar</h2>
|
||||
<h2 id="2rer0ගම්මැද්ද-v-force-ඉනොවේශන්-නේෂන්-සඳහා-එවූ-නි">2rer*(0👍ගම්මැද්ද V FORCE ඉනොවේශන් නේෂන් සඳහා එවූ නි</h2>
|
24
tests/data/slug_heading.md
Normal file
24
tests/data/slug_heading.md
Normal file
@ -0,0 +1,24 @@
|
||||
# foo
|
||||
|
||||
# foo bar
|
||||
|
||||
# foo_bar
|
||||
|
||||
# foo+bar
|
||||
|
||||
# 2rer*(0👍ගම්මැද්ද V FORCE ඉනොවේශන් නේෂන් සඳහා එවූ නි
|
||||
|
||||
foo
|
||||
---
|
||||
|
||||
foo bar
|
||||
---
|
||||
|
||||
foo_bar
|
||||
---
|
||||
|
||||
foo+bar
|
||||
---
|
||||
|
||||
2rer*(0👍ගම්මැද්ද V FORCE ඉනොවේශන් නේෂන් සඳහා එවූ නි
|
||||
---
|
38
tests/src/Configurables/HeaderSlugTest.php
Normal file
38
tests/src/Configurables/HeaderSlugTest.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Erusev\Parsedown\Tests\Configurables;
|
||||
|
||||
use Erusev\Parsedown\Configurables\HeaderSlug;
|
||||
use Erusev\Parsedown\State;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class HeaderSlugTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
* @throws \PHPUnit\Framework\ExpectationFailedException
|
||||
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
|
||||
*/
|
||||
public function testNamedConstructor()
|
||||
{
|
||||
$State = new State([HeaderSlug::enabled()]);
|
||||
|
||||
$this->assertSame(true, $State->get(HeaderSlug::class)->isEnabled());
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
* @throws \PHPUnit\Framework\ExpectationFailedException
|
||||
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
|
||||
*/
|
||||
public function testCustomCallback()
|
||||
{
|
||||
$HeaderSlug = HeaderSlug::withCallback(function (string $t): string {
|
||||
return \preg_replace('/[^A-Za-z0-9]++/', '_', $t);
|
||||
});
|
||||
|
||||
$this->assertSame(
|
||||
'foo_bar',
|
||||
$HeaderSlug->transform('foo bar')
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user