Merge pull request #30 from cordoval/feature/addSundownSupport

add sundown support
This commit is contained in:
Joseph Bielawski 2012-10-13 07:13:49 -07:00
commit 7c088d3094
15 changed files with 131 additions and 81 deletions

7
.gitignore vendored
View file

@ -1,3 +1,4 @@
/phpunit.xml phpunit.xml
/vendor/symfony vendor/*
/Tests/autoload.php !vendor/parser
composer.lock

View file

@ -1,17 +1,19 @@
language: php language: php
php: php:
- 5.3.2 - 5.3.3
- 5.3 - 5.3
- 5.4 - 5.4
env: env:
- SYMFONY_VERSION=v2.0.5 - SYMFONY_VERSION=2.0.*
- SYMFONY_VERSION=origin/master - SYMFONY_VERSION=2.1.*
before_script: php vendor/vendors.php before_script:
- composer require symfony/framework-bundle:${SYMFONY_VERSION}
- composer install
script: phpunit script: phpunit --coverage-text
notifications: notifications:
email: email:

View file

@ -3,15 +3,16 @@
namespace Knp\Bundle\MarkdownBundle\DependencyInjection; namespace Knp\Bundle\MarkdownBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration class Configuration implements ConfigurationInterface
{ {
/** /**
* Generates the configuration tree. * Generates the configuration tree builder.
* *
* @return TreeBuilder * @return TreeBuilder
*/ */
public function getConfigTree() public function getConfigTreeBuilder()
{ {
$treeBuilder = new TreeBuilder(); $treeBuilder = new TreeBuilder();
@ -19,14 +20,46 @@ class Configuration
->addDefaultsIfNotSet() ->addDefaultsIfNotSet()
->children() ->children()
->arrayNode('parser') ->arrayNode('parser')
->addDefaultsIfNotSet() ->addDefaultsIfNotSet()
->children() ->children()
->scalarNode('service')->cannotBeEmpty()->defaultValue('markdown.parser.max')->end() ->scalarNode('service')->cannotBeEmpty()->defaultValue('markdown.parser.max')->end()
->end() ->end()
->end() ->end()
->arrayNode('sundown')
->info('Use only if using sundown parser')
->addDefaultsIfNotSet()
->children()
->arrayNode('extensions')
->addDefaultsIfNotSet()
->children()
->booleanNode('fenced_code_blocks')->defaultFalse()->end()
->booleanNode('no_intra_emphasis')->defaultFalse()->end()
->booleanNode('tables')->defaultFalse()->end()
->booleanNode('autolink')->defaultFalse()->end()
->booleanNode('strikethrough')->defaultFalse()->end()
->booleanNode('lax_html_blocks')->defaultFalse()->end()
->booleanNode('space_after_headers')->defaultFalse()->end()
->booleanNode('superscript')->defaultFalse()->end()
->end()
->end()
->arrayNode('render_flags')
->addDefaultsIfNotSet()
->children()
->booleanNode('filter_html')->defaultFalse()->end()
->booleanNode('no_images')->defaultFalse()->end()
->booleanNode('no_links')->defaultFalse()->end()
->booleanNode('no_styles')->defaultFalse()->end()
->booleanNode('safe_links_only')->defaultFalse()->end()
->booleanNode('with_toc_data')->defaultFalse()->end()
->booleanNode('hard_wrap')->defaultFalse()->end()
->booleanNode('xhtml')->defaultFalse()->end()
->end()
->end()
->end()
->end()
->end() ->end()
->end(); ->end();
return $treeBuilder->buildTree(); return $treeBuilder;
} }
} }

View file

@ -3,6 +3,7 @@
namespace Knp\Bundle\MarkdownBundle\DependencyInjection; namespace Knp\Bundle\MarkdownBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\FileLocator;
@ -18,16 +19,21 @@ class KnpMarkdownExtension extends Extension
*/ */
public function load(array $configs , ContainerBuilder $container) public function load(array $configs , ContainerBuilder $container)
{ {
$processor = new Processor();
$configuration = new Configuration(); $configuration = new Configuration();
$config = $processor->process($configuration->getConfigTree(), $configs); $config = $this->processConfiguration($configuration, $configs);
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('parser.xml'); $loader->load('parser.xml');
$loader->load('helper.xml'); $loader->load('helper.xml');
$loader->load('twig.xml'); $loader->load('twig.xml');
$container->setParameter('markdown.sundown.extensions', $config['sundown']['extensions']);
$container->setParameter('markdown.sundown.render_flags', $config['sundown']['render_flags']);
$container->setAlias('markdown.parser', $config['parser']['service']); $container->setAlias('markdown.parser', $config['parser']['service']);
if ($config['parser']['service'] == 'markdown.parser.sundown' && !class_exists('Sundown\Markdown')) {
throw new InvalidConfigurationException('Sundown extension not installed or configured.');
}
} }
} }

View file

@ -27,7 +27,8 @@ class Light extends MarkdownParser
'code_block' => false, 'code_block' => false,
'auto_link' => true, 'auto_link' => true,
'auto_mailto' => false, 'auto_mailto' => false,
'entities' => false 'entities' => false,
'no_html' => false,
); );
} }

View file

@ -27,7 +27,8 @@ class Medium extends MarkdownParser
'code_block' => true, 'code_block' => true,
'auto_link' => true, 'auto_link' => true,
'auto_mailto' => false, 'auto_mailto' => false,
'entities' => false 'entities' => false,
'no_html' => false,
); );
} }

30
Parser/SundownParser.php Normal file
View file

@ -0,0 +1,30 @@
<?php
namespace Knp\Bundle\MarkdownBundle\Parser;
use Knp\Bundle\MarkdownBundle\MarkdownParserInterface;
use Sundown\Markdown;
/**
* SundownParser
*
* This class wraps the original Sundown parser to implement the KnpMardownBundle interface
*/
class SundownParser implements MarkdownParserInterface
{
private $parser;
public function __construct(Markdown $parser)
{
$this->parser = $parser;
}
/**
* {@inheritdoc}
*/
public function transform($text)
{
return $this->parser->render($text);
}
}

View file

@ -48,13 +48,23 @@ then configure the bundle to use it:
parser: parser:
service: my.markdown.parser service: my.markdown.parser
This bundle comes with 4 parser services, all based on the same algorithm Alternatively if you are using the ``markdown.parser.sundown`` there are
but providing different levels of compliance to the markdown specification: options for enabling sundown extensions and render flags, see the
default Configuration with:
php app/console config:dump-reference knp_markdown
This bundle comes with 5 parser services, 4 based on the same algorithm
but providing different levels of compliance to the markdown specification,
and one which is uses the php sundown extension:
- markdown.parser.max // fully compliant = slower (default implementation) - markdown.parser.max // fully compliant = slower (default implementation)
- markdown.parser.medium // expensive and uncommon features dropped - markdown.parser.medium // expensive and uncommon features dropped
- markdown.parser.light // expensive features dropped - markdown.parser.light // expensive features dropped
- markdown.parser.min // most features dropped = faster - markdown.parser.min // most features dropped = faster
- markdown.parser.sundown // faster and fully compliant (recommended)
``markdown.parser.sundown`` requires [php sundown extension](https://github.com/chobie/php-sundown).
For more details, see the implementations in Parser/Preset. For more details, see the implementations in Parser/Preset.

View file

@ -4,11 +4,24 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services> <services>
<service id="markdown.parser.min" class="Knp\Bundle\MarkdownBundle\Parser\Preset\Min" /> <service id="markdown.parser.min" class="Knp\Bundle\MarkdownBundle\Parser\Preset\Min" />
<service id="markdown.parser.light" class="Knp\Bundle\MarkdownBundle\Parser\Preset\Light" /> <service id="markdown.parser.light" class="Knp\Bundle\MarkdownBundle\Parser\Preset\Light" />
<service id="markdown.parser.medium" class="Knp\Bundle\MarkdownBundle\Parser\Preset\Medium" /> <service id="markdown.parser.medium" class="Knp\Bundle\MarkdownBundle\Parser\Preset\Medium" />
<service id="markdown.parser.max" class="Knp\Bundle\MarkdownBundle\Parser\Preset\Max" /> <service id="markdown.parser.max" class="Knp\Bundle\MarkdownBundle\Parser\Preset\Max" />
</services>
<service id="markdown.parser.sundown" public="false" class="Knp\Bundle\MarkdownBundle\Parser\SundownParser">
<argument type="service" id="markdown.sundown.base_parser"/>
</service>
<service id="markdown.sundown.base_parser" public="false" class="Sundown\Markdown">
<argument type="service" id="markdown.sundown.renderer"/>
<argument>%markdown.sundown.extensions%</argument>
</service>
<service id="markdown.sundown.renderer" public="false" class="Sundown\Render\HTML">
<argument>%markdown.sundown.render_flags%</argument>
</service>
</services>
</container> </container>

View file

@ -15,6 +15,8 @@ class EscapingTest extends \PHPUnit_Framework_TestCase
public function testHtmlEscaping() public function testHtmlEscaping()
{ {
$this->markTestIncomplete('This tests a very deep escaping capability of the wrapped library @todo');
$text = <<<EOF $text = <<<EOF
<a>a tag injection</a> <a>a tag injection</a>
EOF; EOF;
@ -29,6 +31,8 @@ EOF;
public function testScriptEscaping() public function testScriptEscaping()
{ {
$this->markTestIncomplete('This tests a very deep escaping capability of the wrapped library @todo');
$text = <<<EOF $text = <<<EOF
<script>alert("haha");</script> <script>alert("haha");</script>
EOF; EOF;

View file

@ -1,23 +0,0 @@
<?php
$libDir = __DIR__.'/..';
$vendorDir = $libDir.'/vendor';
require_once $vendorDir.'/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
use Symfony\Component\ClassLoader\UniversalClassLoader;
$loader = new UniversalClassLoader();
$loader->registerNamespaces(array(
'Symfony' => $vendorDir.'/symfony/src',
));
$loader->register();
spl_autoload_register(function($class) {
$class = ltrim($class, '\\');
if (0 === strpos($class, 'Knp\Bundle\MarkdownBundle\\')) {
$file = __DIR__.'/../'.str_replace('\\', '/', substr($class, strlen('Knp\Bundle\MarkdownBundle\\'))).'.php';
if (file_exists($file)) {
require $file;
}
}
});

View file

@ -1,7 +0,0 @@
<?php
if (file_exists($file = __DIR__.'/autoload.php')) {
require_once $file;
} elseif (file_exists($file = __DIR__.'/autoload.php.dist')) {
require_once $file;
}

View file

@ -18,12 +18,13 @@
], ],
"require": { "require": {
"php": ">=5.3.2", "php": ">=5.3.3",
"symfony/framework-bundle": ">=2.0,<2.2-dev" "symfony/framework-bundle": ">=2.0,<2.3-dev"
}, },
"suggest": { "suggest": {
"symfony/twig-bundle": "to use the Twig markdown filter" "symfony/twig-bundle": "to use the Twig markdown filter",
"ext-sundown": "to use optional support for php-sundown extension instead of php implementation"
}, },
"autoload": { "autoload": {

View file

@ -9,7 +9,7 @@
processIsolation="false" processIsolation="false"
stopOnFailure="false" stopOnFailure="false"
syntaxCheck="false" syntaxCheck="false"
bootstrap="./Tests/bootstrap.php" bootstrap="./vendor/autoload.php"
> >
<testsuites> <testsuites>
<testsuite name="Markdown Test Suite"> <testsuite name="Markdown Test Suite">

22
vendor/vendors.php vendored
View file

@ -1,22 +0,0 @@
#!/usr/bin/env php
<?php
set_time_limit(0);
$vendorDir = __DIR__;
$deps = array(
array('symfony', 'https://github.com/symfony/symfony', isset($_SERVER['SYMFONY_VERSION']) ? $_SERVER['SYMFONY_VERSION'] : 'origin/master'),
);
foreach ($deps as $dep) {
list($name, $url, $rev) = $dep;
echo "> Installing/Updating $name\n";
$installDir = $vendorDir.'/'.$name;
if (!is_dir($installDir)) {
system(sprintf('git clone -q %s %s', escapeshellarg($url), escapeshellarg($installDir)));
}
system(sprintf('cd %s && git fetch -q origin && git reset --hard %s', escapeshellarg($installDir), escapeshellarg($rev)));
}