diff --git a/src/Block/Renderer/BlockQuoteRenderer.php b/src/Block/Renderer/BlockQuoteRenderer.php index e0e9518f02..7815339c7f 100644 --- a/src/Block/Renderer/BlockQuoteRenderer.php +++ b/src/Block/Renderer/BlockQuoteRenderer.php @@ -36,13 +36,13 @@ public function render(AbstractBlock $block, HtmlRenderer $htmlRenderer, $inTigh $filling = $htmlRenderer->renderBlocks($block->getChildren()); if ($filling === '') { - return new HtmlElement('blockquote', array(), $htmlRenderer->getOption('innerSeparator')); + return new HtmlElement('blockquote', array(), $htmlRenderer->getOption('inner_separator', "\n")); } return new HtmlElement( 'blockquote', array(), - $htmlRenderer->getOption('innerSeparator') . $filling . $htmlRenderer->getOption('innerSeparator') + $htmlRenderer->getOption('inner_separator', "\n") . $filling . $htmlRenderer->getOption('inner_separator', "\n") ); } } diff --git a/src/Block/Renderer/ListBlockRenderer.php b/src/Block/Renderer/ListBlockRenderer.php index a3dad10bff..6db346a042 100644 --- a/src/Block/Renderer/ListBlockRenderer.php +++ b/src/Block/Renderer/ListBlockRenderer.php @@ -44,10 +44,10 @@ public function render(AbstractBlock $block, HtmlRenderer $htmlRenderer, $inTigh return new HtmlElement( $tag, $attr, - $htmlRenderer->getOption('innerSeparator') . $htmlRenderer->renderBlocks( + $htmlRenderer->getOption('inner_separator', "\n") . $htmlRenderer->renderBlocks( $block->getChildren(), $block->isTight() - ) . $htmlRenderer->getOption('innerSeparator') + ) . $htmlRenderer->getOption('inner_separator', "\n") ); } } diff --git a/src/CommonMarkConverter.php b/src/CommonMarkConverter.php index b3f40e94ce..f67dbc4ee7 100644 --- a/src/CommonMarkConverter.php +++ b/src/CommonMarkConverter.php @@ -35,10 +35,13 @@ class CommonMarkConverter /** * Create a new commonmark converter instance. + * + * @param array $config */ - public function __construct() + public function __construct(array $config = array()) { $environment = Environment::createCommonMarkEnvironment(); + $environment->mergeConfig($config); $this->docParser = new DocParser($environment); $this->htmlRenderer = new HtmlRenderer($environment); } diff --git a/src/Environment.php b/src/Environment.php index 6ed9fcf8f9..ac40911ecd 100644 --- a/src/Environment.php +++ b/src/Environment.php @@ -70,9 +70,73 @@ class Environment */ protected $inlineRenderersByClass = array(); - public function __construct() + /** + * @var array + */ + protected $config; + + public function __construct(array $config = array()) { $this->miscExtension = new MiscExtension(); + $this->config = $config; + } + + /** + * @param array $config + */ + public function mergeConfig(array $config = array()) + { + if ($this->extensionsInitialized) { + throw new \RuntimeException('Failed to modify configuration - extensions have already been initialized'); + } + + $this->config = array_replace_recursive($this->config, $config); + } + + /** + * @param array $config + */ + public function setConfig(array $config = array()) + { + if ($this->extensionsInitialized) { + throw new \RuntimeException('Failed to modify configuration - extensions have already been initialized'); + } + + $this->config = $config; + } + + /** + * @param string|null $key + * @param mixed|null $default + * + * @return mixed|null + */ + public function getConfig($key = null, $default = null) + { + // accept a/b/c as ['a']['b']['c'] + if (strpos($key, '/')) { + $keyArr = explode('/', $key); + $data = $this->config; + foreach ($keyArr as $k) { + if (!is_array($data) || !isset($data[$k])) { + return $default; + } + + $data = $data[$k]; + } + + return $data; + } + + if ($key === null) { + return $this->config; + } + + if (!isset($this->config[$key])) { + return $default; + } + + return $this->config[$key]; } /** @@ -397,6 +461,13 @@ public static function createCommonMarkEnvironment() { $environment = new static(); $environment->addExtension(new CommonMarkCoreExtension()); + $environment->mergeConfig(array( + 'renderer' => array( + 'block_separator' => "\n", + 'inner_separator' => "\n", + 'soft_break' => "\n", + ) + )); return $environment; } diff --git a/src/HtmlRenderer.php b/src/HtmlRenderer.php index b04a3a3754..f5c74d747d 100644 --- a/src/HtmlRenderer.php +++ b/src/HtmlRenderer.php @@ -28,33 +28,22 @@ class HtmlRenderer protected $environment; /** - * @var array + * @param Environment $environment */ - protected $options; - - /** - * @param array $options - */ - public function __construct(Environment $environment, array $options = array()) + public function __construct(Environment $environment) { $this->environment = $environment; - - $defaults = array( - 'blockSeparator' => "\n", - 'innerSeparator' => "\n", - 'softBreak' => "\n" - ); - $this->options = array_merge($defaults, $options); } /** * @param string $option + * @param mixed|null $default * * @return mixed|null */ - public function getOption($option) + public function getOption($option, $default = null) { - return $this->options[$option]; + return $this->environment->getConfig('renderer/' . $option, $default); } /** @@ -137,6 +126,8 @@ public function renderBlocks($blocks, $inTightList = false) $result[] = $this->renderBlock($block, $inTightList); } - return implode($this->options['blockSeparator'], $result); + $separator = $this->getOption('block_separator', "\n"); + + return implode($separator, $result); } } diff --git a/src/Inline/Renderer/NewlineRenderer.php b/src/Inline/Renderer/NewlineRenderer.php index adbc47beed..2e9a9eba2b 100644 --- a/src/Inline/Renderer/NewlineRenderer.php +++ b/src/Inline/Renderer/NewlineRenderer.php @@ -36,7 +36,7 @@ public function render(AbstractInline $inline, HtmlRenderer $htmlRenderer) if ($inline->getType() === Newline::HARDBREAK) { return new HtmlElement('br', array(), '', true) . "\n"; } else { - return $htmlRenderer->getOption('softBreak'); + return $htmlRenderer->getOption('soft_break', "\n"); } } } diff --git a/tests/EnvironmentTest.php b/tests/EnvironmentTest.php index 64550f6fcb..0a4656e9ed 100644 --- a/tests/EnvironmentTest.php +++ b/tests/EnvironmentTest.php @@ -34,4 +34,76 @@ public function testAddGetExtensions() $this->assertCount(1, $extensions); $this->assertEquals($extension, $extensions['foo']); } + + public function testConstructor() + { + $config = array('foo' => 'bar'); + $environment = new Environment($config); + $this->assertEquals('bar', $environment->getConfig('foo')); + } + + public function testGetConfig() + { + $config = array( + 'foo' => 'bar', + 'a' => array( + 'b' => 'c' + ) + ); + $environment = new Environment($config); + + // No arguments should return the whole thing + $this->assertEquals($config, $environment->getConfig()); + + // Test getting a single scalar element + $this->assertEquals('bar', $environment->getConfig('foo')); + + // Test getting a single array element + $this->assertEquals($config['a'], $environment->getConfig('a')); + + // Test getting an element by path + $this->assertEquals('c', $environment->getConfig('a/b')); + + // Test getting a non-existent element + $this->assertNull($environment->getConfig('test')); + + // Test getting a non-existent element with a default value + $this->assertEquals(42, $environment->getConfig('answer', 42)); + } + + public function testSetConfig() + { + $environment = new Environment(array('foo' => 'bar')); + $environment->setConfig(array('test' => '123')); + $this->assertNull($environment->getConfig('foo')); + $this->assertEquals('123', $environment->getConfig('test')); + } + + public function testSetConfigAfterInit() + { + $this->setExpectedException('RuntimeException'); + + $environment = new Environment(); + // This triggers the initialization + $environment->getBlockParsers(); + $environment->setConfig(array('foo' => 'bar')); + } + + public function testMergeConfig() + { + $environment = new Environment(array('foo' => 'bar', 'test' => '123')); + $environment->mergeConfig(array('test' => '456')); + $this->assertEquals('bar', $environment->getConfig('foo')); + $this->assertEquals('456', $environment->getConfig('test')); + } + + public function testMergeConfigAfterInit() + { + $this->setExpectedException('RuntimeException'); + + $environment = new Environment(); + // This triggers the initialization + $environment->getBlockParsers(); + $environment->mergeConfig(array('foo' => 'bar')); + } } \ No newline at end of file