Skip to content

Commit

Permalink
Merge pull request #3 from noxify/master
Browse files Browse the repository at this point in the history
Gist and Codepen shortcode
  • Loading branch information
johnnyhuy authored Dec 12, 2018
2 parents 2c5ff57 + d4834c5 commit 18259da
Show file tree
Hide file tree
Showing 21 changed files with 414 additions and 38 deletions.
6 changes: 3 additions & 3 deletions src/Block/Element/Color.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

namespace JohnnyHuy\Laravel\Block\Element;

use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Element\InlineContainerInterface;
use League\CommonMark\ContextInterface;
use League\CommonMark\Cursor;
use League\CommonMark\Util\RegexHelper;
use League\CommonMark\ContextInterface;
use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Element\InlineContainerInterface;

class Color extends AbstractBlock implements InlineContainerInterface {
/**
Expand Down
6 changes: 3 additions & 3 deletions src/Block/Element/TextAlignment.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

namespace JohnnyHuy\Laravel\Block\Element;

use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Element\InlineContainerInterface;
use League\CommonMark\ContextInterface;
use League\CommonMark\Cursor;
use League\CommonMark\Util\RegexHelper;
use League\CommonMark\ContextInterface;
use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Element\InlineContainerInterface;

class TextAlignment extends AbstractBlock implements InlineContainerInterface {
/**
Expand Down
5 changes: 2 additions & 3 deletions src/Block/Parser/ColorParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

namespace JohnnyHuy\Laravel\Block\Parser;

use League\CommonMark\Cursor;
use League\CommonMark\ContextInterface;
use JohnnyHuy\Laravel\Block\Element\Color;
use JohnnyHuy\Laravel\Block\Element\TextAlignment;
use League\CommonMark\Block\Parser\AbstractBlockParser;
use League\CommonMark\ContextInterface;
use League\CommonMark\Cursor;

/**
* Text alignment parser class.
Expand Down
4 changes: 2 additions & 2 deletions src/Block/Parser/TextAlignmentParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

namespace JohnnyHuy\Laravel\Block\Parser;

use League\CommonMark\Cursor;
use League\CommonMark\ContextInterface;
use JohnnyHuy\Laravel\Block\Element\TextAlignment;
use League\CommonMark\Block\Parser\AbstractBlockParser;
use League\CommonMark\ContextInterface;
use League\CommonMark\Cursor;

/**
* Text alignment parser class.
Expand Down
9 changes: 4 additions & 5 deletions src/Block/Renderer/ColorRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

namespace JohnnyHuy\Laravel\Block\Renderer;

use League\CommonMark\HtmlElement;
use League\CommonMark\Util\Configuration;
use JohnnyHuy\Laravel\Block\Element\Color;
use JohnnyHuy\Laravel\Block\Element\TextAlignment;
use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Renderer\BlockRendererInterface;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Util\Configuration;
use League\CommonMark\Block\Renderer\BlockRendererInterface;

class ColorRenderer implements BlockRendererInterface
{
Expand Down
8 changes: 4 additions & 4 deletions src/Block/Renderer/TextAlignmentRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

namespace JohnnyHuy\Laravel\Block\Renderer;

use League\CommonMark\HtmlElement;
use League\CommonMark\Util\Configuration;
use League\CommonMark\ElementRendererInterface;
use JohnnyHuy\Laravel\Block\Element\TextAlignment;
use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Renderer\BlockRendererInterface;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Util\Configuration;
use League\CommonMark\Block\Renderer\BlockRendererInterface;

class TextAlignmentRenderer implements BlockRendererInterface
{
Expand Down
7 changes: 7 additions & 0 deletions src/Inline/Element/Codepen.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace JohnnyHuy\Laravel\Inline\Element;

use League\CommonMark\Inline\Element\AbstractWebResource;

class Codepen extends AbstractWebResource {}
7 changes: 7 additions & 0 deletions src/Inline/Element/Gist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace JohnnyHuy\Laravel\Inline\Element;

use League\CommonMark\Inline\Element\AbstractWebResource;

class Gist extends AbstractWebResource {}
52 changes: 52 additions & 0 deletions src/Inline/Parser/CodepenParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types = 1);

namespace JohnnyHuy\Laravel\Inline\Parser;

use League\CommonMark\InlineParserContext;
use JohnnyHuy\Laravel\Inline\Element\Codepen;
use League\CommonMark\Inline\Parser\AbstractInlineParser;

class CodepenParser extends AbstractInlineParser
{
/**
* @param InlineParserContext $inlineContext
* @return bool
*/
public function parse(InlineParserContext $inlineContext)
{
$cursor = $inlineContext->getCursor();
$savedState = $cursor->saveState();

$cursor->advance();

//check that the given user input is a valid codepen url
//and the required `codepen:` prefix exists
$regex = '/^(?:codepen)\s(https:\/\/codepen\.io\/([^\/]+\/)?([a-zA-Z0-9]+)\/pen\/([a-zA-Z0-9]+)?)/';
$validate = $cursor->match($regex);

//the computer says no
if (!$validate) {
$cursor->restoreState($savedState);

return false;
}

$matches = [];
preg_match($regex, $validate, $matches);

//return the given codepen url to the renderer class
$inlineContext->getContainer()->appendChild(new Codepen($matches[1]));

return true;
}

/**
* @return string[]
*/
public function getCharacters()
{
return [':'];
}
}
52 changes: 52 additions & 0 deletions src/Inline/Parser/GistParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types = 1);

namespace JohnnyHuy\Laravel\Inline\Parser;

use JohnnyHuy\Laravel\Inline\Element\Gist;
use League\CommonMark\InlineParserContext;
use League\CommonMark\Inline\Parser\AbstractInlineParser;

class GistParser extends AbstractInlineParser
{
/**
* @param InlineParserContext $inlineContext
* @return bool
*/
public function parse(InlineParserContext $inlineContext)
{
$cursor = $inlineContext->getCursor();
$savedState = $cursor->saveState();

$cursor->advance();

//check that the given user input is a valid gist url
//and the required `gist:` prefix exists
$regex = '/^(?:gist)\s(https:\/\/gist.github.com\/([^\/]+\/)?([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)?)/';
$validate = $cursor->match($regex);

//the computer says no
if (!$validate) {
$cursor->restoreState($savedState);

return false;
}

$matches = [];
preg_match($regex, $validate, $matches);

//return the given gist url to the renderer class
$inlineContext->getContainer()->appendChild(new Gist($matches[1]));

return true;
}

/**
* @return string[]
*/
public function getCharacters()
{
return [':'];
}
}
6 changes: 4 additions & 2 deletions src/Inline/Parser/SoundCloudParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

namespace JohnnyHuy\Laravel\Inline\Parser;

use League\CommonMark\InlineParserContext;
use JohnnyHuy\Laravel\Inline\Element\SoundCloud;
use JohnnyHuy\Laravel\Inline\Element\YouTube;
use League\CommonMark\Inline\Parser\AbstractInlineParser;
use League\CommonMark\InlineParserContext;

class SoundCloudParser extends AbstractInlineParser
{
Expand All @@ -22,9 +21,12 @@ public function parse(InlineParserContext $inlineContext)

$cursor->advance();

//check that the given user input is a valid soundcloud url
//and the required `soundcloud:` or `:sc` prefix exists
$regex = '/^(?:soundcloud|sc)\s((?:https?\:\/\/)?(?:www\.)?(?:soundcloud\.com\/)[^&#\s\?]+\/[^&#\s\?]+)/';
$validate = $cursor->match($regex);

//the computer says no
if (!$validate) {
$cursor->restoreState($savedState);

Expand Down
6 changes: 5 additions & 1 deletion src/Inline/Parser/YouTubeParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace JohnnyHuy\Laravel\Inline\Parser;

use League\CommonMark\InlineParserContext;
use JohnnyHuy\Laravel\Inline\Element\YouTube;
use League\CommonMark\Inline\Parser\AbstractInlineParser;
use League\CommonMark\InlineParserContext;

class YouTubeParser extends AbstractInlineParser
{
Expand All @@ -21,9 +21,12 @@ public function parse(InlineParserContext $inlineContext)

$cursor->advance();

//regex to ensure that we got a valid youtube url
//and the required `youtube:` prefix exists
$regex = '/^(?:youtube)\s(?:https?\:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&#\s\?]+)(?:\?.[^\s]+)?/';
$validate = $cursor->match($regex);

//the computer says no
if (!$validate) {
$cursor->restoreState($savedState);

Expand All @@ -34,6 +37,7 @@ public function parse(InlineParserContext $inlineContext)
preg_match($regex, $validate, $matches);
$videoId = $matches[1];

//generates a valid youtube embed url with the parsed video id from the given url
$inlineContext->getContainer()->appendChild(new YouTube("https://www.youtube.com/embed/$videoId"));

return true;
Expand Down
60 changes: 60 additions & 0 deletions src/Inline/Renderer/CodepenRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace JohnnyHuy\Laravel\Inline\Renderer;

use League\CommonMark\HtmlElement;
use League\CommonMark\Util\Configuration;
use JohnnyHuy\Laravel\Inline\Element\Codepen;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Util\ConfigurationAwareInterface;
use League\CommonMark\Inline\Element\AbstractWebResource;
use League\CommonMark\Inline\Renderer\InlineRendererInterface;

class CodepenRenderer implements InlineRendererInterface
{
/**
* @var Configuration
*/
protected $config;

/**
* @param AbstractInline|AbstractWebResource $inline
* @param \League\CommonMark\ElementRendererInterface $htmlRenderer
*
* @return \League\CommonMark\HtmlElement|string
* @throws \ErrorException
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Codepen)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline));
}

// Use a oEmbed route to get codepen details
$apiUrl = "https://codepen.io/api/oembed?url={$inline->getUrl()}&format=json";

$apiResponse = $this->getContent($apiUrl);

//seems that the used codepen url is invalid
//or codepen is currently not available
if (is_null($apiResponse)) {
throw new \ErrorException('Codepen request returned null: ' . $apiUrl);
}

//parse the oembed response
$embed = json_decode($apiResponse);

//return the oembed html snippet with a div as wrapper element
return new HtmlElement('div', ['class' => 'codepen-container'], $embed->html);
}

/**
* @param string $url
* @return string
*/
public function getContent(string $url): string
{
return file_get_contents($url);
}
}
51 changes: 51 additions & 0 deletions src/Inline/Renderer/GistRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace JohnnyHuy\Laravel\Inline\Renderer;

use League\CommonMark\HtmlElement;
use League\CommonMark\Util\Configuration;
use JohnnyHuy\Laravel\Inline\Element\Gist;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Util\ConfigurationAwareInterface;
use League\CommonMark\Inline\Element\AbstractWebResource;
use League\CommonMark\Inline\Renderer\InlineRendererInterface;

class GistRenderer implements InlineRendererInterface
{
/**
* @var Configuration
*/
protected $config;

/**
* @param AbstractInline|AbstractWebResource $inline
* @param \League\CommonMark\ElementRendererInterface $htmlRenderer
*
* @return \League\CommonMark\HtmlElement|string
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Gist)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline));
}

//generates the same script element, which you can see
//in the "embed gist" input field
$script = new HtmlElement('script', [
'src' => $inline->getUrl().'.js'
]);

//add a div wrapper around the script element
return new HtmlElement('div', ['class' => 'gist-container'], $script);
}

/**
* @param string $url
* @return string
*/
public function getContent(string $url) : string
{
return file_get_contents($url);
}
}
Loading

0 comments on commit 18259da

Please sign in to comment.