Skip to content

Commit

Permalink
Merge pull request #5 from dereuromark/bbcode-markdown
Browse files Browse the repository at this point in the history
Add BBCode and Markdown wrappers.
  • Loading branch information
dereuromark authored Sep 19, 2020
2 parents d082ce0 + a74b7a0 commit 6bf3c9a
Show file tree
Hide file tree
Showing 23 changed files with 1,084 additions and 76 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ before_script:
script:
- if [[ $DEFAULT == 1 ]]; then vendor/bin/phpunit; fi

- if [[ $CHECKS == 1 ]]; then composer cs-check ; fi
- if [[ $CHECKS == 1 ]]; then composer phpstan-setup && composer phpstan; fi
- if [[ $CHECKS == 1 ]]; then composer cs-check; fi
- if [[ $CHECKS == 1 ]]; then composer stan-setup && composer stan; fi

- if [[ $CODECOVERAGE == 1 ]]; then vendor/bin/phpunit --coverage-clover=clover.xml || true; fi
- if [[ $CODECOVERAGE == 1 ]]; then wget -O codecov.sh https://codecov.io/bash; fi
Expand Down
67 changes: 3 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

A CakePHP plugin to
- easily use code syntax highlighters.
- quickly convert Markdown snippets.
- quickly convert BBCode snippets.

This branch is for **CakePHP 4.0+**. See [version map](https://github.com/dereuromark/cakephp-markup/wiki#cakephp-version-map) for details.

Expand All @@ -25,70 +27,7 @@ https://sandbox.dereuromark.de/sandbox/markup-examples

## Usage

```php
// You must load the helper before
$this->loadHelper('Markup.Highlighter', $optionalConfigArray);

// In our ctp file we can now highlight some code snippet
$string = <<<'TEXT'
$result = 'string' . $this->request->query('key'); // Some comment
TEXT;

echo $this->Highlighter->highlight($string, ['lang' => 'php']);
```

### Supported Highlighters

#### PhpHighlighter
Using native PHP syntax highlighting this default highlighter does not need any dependencies.
Just add some basic CSS styling for all `<pre>` tags.

The output will be automatically escaped (safe) HTML code, e.g. for `php` language code:
```html
<pre class="lang-php"><code>
<span style="color: #000000">$key&nbsp;=&nbsp;'string'&nbsp;.&nbsp;$this-&gt;something-&gt;do(true);&nbsp;//&nbsp;Some&nbsp;comment</span>
</code></pre>
```

#### JsHighlighter
Using only JS via [highlightjs.org](https://highlightjs.org/) or [prismjs.com](http://prismjs.com/) this parser is lightweight on the server side.
It requires a CSS and JS file on top to do client-side highlighting "just in time".
```php
// Helper option
'highlighter' => 'Markup\Highlighter\JsHighlighter',
```

The output for `php` language code will be wrapped in
```html
<pre><code class="language-php">...</code></pre>
```
tags, for example.
Do not forget to add your custom code style CSS file and the JS code as documented at [highlightjs.org](https://highlightjs.org/usage/) or [prismjs.com](http://prismjs.com/#basic-usage).

### Write your own highlighter
You just have to implement the `HighlighterInterface` and ideally extend the abstract `Highlighter` class.
Then you can simply switch your code highlighting on demand or globally with Configure:
```php
// Configure
'Highlighter' => [
'highlighter' => 'VendorName\PluginName\CustomHighlighter',
],
```

You should be able to easily use any custom highlighter this way.

If you are looking for a good auto-detection highlighter, take a look at [github.com/google/code-prettify](https://github.com/google/code-prettify).
In case you need the full options stack, it would be best to write a custom one here, otherwise a basic code template `<pre class="prettyprint">{{content}}</pre>` for `JsHighlighter` should do the trick.

### Additional Configuration
You can switch the template to use `<div>` instead of `<pre`> for example:
```php
// Helper option
'templates' => [
'code' => '<div{{attr}}>{{content}}</div>',
],
```
See [Docs](/docs).

## TODO
- Add more highlighters (you can also just link your own here)
- Add markup parsers and possibly View classes (BBCode, Markdown, ...)
9 changes: 6 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
"cakephp/cakephp": "^4.0.0"
},
"require-dev": {
"fig-r/psr2r-sniffer": "dev-master"
"fig-r/psr2r-sniffer": "dev-master",
"league/commonmark": "^1.5",
"mjohnson/decoda": "^6.12",
"dereuromark/media-embed": "^0.5"
},
"autoload": {
"psr-4": {
Expand All @@ -34,8 +37,8 @@
"source": "https://github.com/dereuromark/cakephp-markup"
},
"scripts": {
"phpstan": "phpstan analyse -c tests/phpstan.neon -l 5 src/",
"phpstan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12 && mv composer.backup composer.json",
"stan": "phpstan analyse -c tests/phpstan.neon src/",
"stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12 && mv composer.backup composer.json",
"test": "php phpunit.phar",
"test-setup": "[ ! -f phpunit.phar ] && wget https://phar.phpunit.de/phpunit-8.4.3.phar && mv phpunit-8.4.3.phar phpunit.phar || true",
"test-coverage": "php phpunit.phar --log-junit tmp/coverage/unitreport.xml --coverage-html tmp/coverage --coverage-clover tmp/coverage/coverage.xml",
Expand Down
112 changes: 112 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Documentation

## Highlighter

```php
// You must load the helper before
$this->loadHelper('Markup.Highlighter', $optionalConfigArray);

// In our template file we can now highlight some code snippet
$string = <<<'TEXT'
$result = 'string' . $this->request->query('key'); // Some comment
TEXT;

echo $this->Highlighter->highlight($string, ['lang' => 'php']);
```

### Supported Highlighters

#### PhpHighlighter
Using native PHP syntax highlighting this default highlighter does not need any dependencies.
Just add some basic CSS styling for all `<pre>` tags.

The output will be automatically escaped (safe) HTML code, e.g. for `php` language code:
```html
<pre class="lang-php"><code>
<span style="color: #000000">$key&nbsp;=&nbsp;'string'&nbsp;.&nbsp;$this-&gt;something-&gt;do(true);&nbsp;//&nbsp;Some&nbsp;comment</span>
</code></pre>
```

#### JsHighlighter
Using only JS via [highlightjs.org](https://highlightjs.org/) or [prismjs.com](http://prismjs.com/) this parser is lightweight on the server side.
It requires a CSS and JS file on top to do client-side highlighting "just in time".
```php
// Helper option
'highlighter' => 'Markup\Highlighter\JsHighlighter',
```

The output for `php` language code will be wrapped in
```html
<pre><code class="language-php">...</code></pre>
```
tags, for example.
Do not forget to add your custom code style CSS file and the JS code as documented at [highlightjs.org](https://highlightjs.org/usage/) or [prismjs.com](http://prismjs.com/#basic-usage).

### Write your own highlighter
You just have to implement the `HighlighterInterface` and ideally extend the abstract `Highlighter` class.
Then you can simply switch your code highlighting on demand or globally with Configure:
```php
// Configure
'Highlighter' => [
'highlighter' => 'VendorName\PluginName\CustomHighlighter',
],
```

You should be able to easily use any custom highlighter this way.

If you are looking for a good auto-detection highlighter, take a look at [github.com/google/code-prettify](https://github.com/google/code-prettify).
In case you need the full options stack, it would be best to write a custom one here, otherwise a basic code template `<pre class="prettyprint">{{content}}</pre>` for `JsHighlighter` should do the trick.

### Additional Configuration
You can switch the template to use `<div>` instead of `<pre`> for example:
```php
// Helper option
'templates' => [
'code' => '<div{{attr}}>{{content}}</div>',
],
```

## Markdown

For this you need to decide on a converter library.
By default, the included `CommonMarkMarkdown` class requires you to install its dependency:
```
composer require league/commonmark
```

Once you configured it the way you want it you can start using it.

```php
// You must load the helper before
$this->loadHelper('Markup.Markdown', $optionalConfigArray);

// In our template file we can now convert some markdown code snippet
$string = <<<'TEXT'
Some **bold** text and also some *italic*.
TEXT;

echo $this->Markdown->convert($string);
```


## BBCode

For this you need to decide on a converter library.
By default, the included `DecodaBbcode` class requires you to install its dependency:
```
composer require mjohnson/decoda
```

Once you configured it the way you want it you can start using it.

```php
// You must load the helper before
$this->loadHelper('Markup.Bbcode', $optionalConfigArray);

// In our template file we can now convert some markdown code snippet
$string = <<<'TEXT'
Some [b]bold[/b] text and also some [i]italic[/i].
TEXT;

echo $this->Bbcode->convert($string);
```
19 changes: 19 additions & 0 deletions src/Bbcode/BbcodeInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Markup\Bbcode;

interface BbcodeInterface {

/**
* Convert BBCode markup to HTML.
*
* Options:
* - escape
*
* @param string $text
* @param array $options
* @return string
*/
public function convert(string $text, array $options = []): string;

}
94 changes: 94 additions & 0 deletions src/Bbcode/Decoda/VideoFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Markup\Bbcode\Decoda;

use Decoda\Decoda;
use Decoda\Filter\AbstractFilter;
use MediaEmbed\MediaEmbed;

class VideoFilter extends AbstractFilter {

/**
* Regex pattern.
*/
public const VIDEO_PATTERN = '/^[-_a-z0-9]+$/is';
public const SIZE_PATTERN = '/^(?:small|medium|large)$/i';

/**
* @var \MediaEmbed\MediaEmbed
*/
protected $MediaEmbed;

/**
* Supported tags.
*
* @var array
*/
protected $_tags = [
'video' => [
'template' => 'video',
'displayType' => Decoda::TYPE_BLOCK,
'allowedTypes' => Decoda::TYPE_NONE,
'contentPattern' => self::VIDEO_PATTERN,
'attributes' => [
'default' => self::ALPHA,
'size' => self::SIZE_PATTERN,
],
],
];

/**
* Custom build the HTML for videos.
*
* @param array $tag
* @param string $content
* @return string
*/
public function parse(array $tag, $content) {
$provider = isset($tag['attributes']['default']) ? $tag['attributes']['default'] : $tag['tag'];
//$size = mb_strtolower(isset($tag['attributes']['size']) ? $tag['attributes']['size'] : 'medium');

preg_match('/^\[video\s*=\s*([a-z0-9_-]+)\]$/i', $tag['text'], $matches);
if (!$matches) {
return $tag['text'] . $content . '[/' . $tag['tag'] . ']';
}

$provider = $matches[1];
$result = $this->transform($provider, $content);
if (!$result) {
return $tag['text'] . $content . '[/' . $tag['tag'] . ']';
}

return $result;
}

/**
* @param string $provider
* @param string $id
*
* @return string|null
*/
protected function transform($provider, $id) {
// timestamp?
if (strpos($id, ',') !== false) {
[$id, $t] = explode(',', $id, 2);
}
if (!empty($t)) {
// with timestamps we cannot use the embed mode...
//TODO
}

if (!isset($this->MediaEmbed)) {
$this->MediaEmbed = new MediaEmbed();
}
$MediaObject = $this->MediaEmbed->parseId($id, $provider);
if (!$MediaObject) {
return null;
}

$MediaObject->setAttribute('width', '100%');

return $MediaObject->getEmbedCode();
}

}
Loading

0 comments on commit 6bf3c9a

Please sign in to comment.