Skip to content
This repository has been archived by the owner on Apr 4, 2020. It is now read-only.

Commit

Permalink
Deprecate extension (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
colinodell authored Apr 4, 2020
1 parent 9b10753 commit 1e90bb2
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 192 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased][unreleased]

## [1.1.0] - 2020-04-01

### Deprecated

**This extension has been deprecated**. All of its functionality now exists in league/commonmark 1.3+ under the `League\CommonMark\Extension\Autolink` namespace.

## [1.0.1] - 2020-01-13

### Fixed
Expand Down Expand Up @@ -75,7 +81,8 @@ This release brings the email and URL autolink processors into alignment with th

Initial release!

[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.1...HEAD
[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.1.0...HEAD
[1.1.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.1...v1.1.0
[1.0.1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta3...v1.0.0
[1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta2...v1.0.0-beta3
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
[![Quality Score][ico-code-quality]][link-code-quality]
[![Total Downloads][ico-downloads]][link-downloads]

## DEPRECATED

**This extension has been deprecated**. All of its functionality now exists in [`league/commonmark`][link-league-commonmark] 1.3+ under the `League\CommonMark\Extension\Autolink` namespace, so you should upgrade to that version and use that bundled extension instead of this one.

## Overview

This extension adds [GFM-style autolinking][link-gfm-spec-autolinking] to the [`league/commonmark` Markdown parser for PHP][link-league-commonmark]. It automatically link URLs and email addresses even when the CommonMark `<...>` autolink syntax is not used.

It also provides a parser to autolink `@mentions` to Twitter, Github, or any custom service you wish, though this is disabled by default.
Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
],
"require": {
"php" : "^7.1",
"league/commonmark": "^1.0"
"league/commonmark": "^1.3"
},
"require-dev": {
"phpunit/phpunit": "^7.5"
Expand All @@ -35,7 +35,8 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
"dev-master": "1.2-dev"
}
}
},
"abandoned": "league/commonmark"
}
16 changes: 13 additions & 3 deletions src/AutolinkExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,24 @@
namespace League\CommonMark\Ext\Autolink;

use League\CommonMark\ConfigurableEnvironmentInterface;
use League\CommonMark\Event\DocumentParsedEvent;
use League\CommonMark\Extension\Autolink\AutolinkExtension as CoreExtension;
use League\CommonMark\Extension\ExtensionInterface;

/**
* @deprecated The league/commonmark-ext-autolink extension is now deprecated. All functionality has been moved into league/commonmark 1.3+, so use that instead.
*/
final class AutolinkExtension implements ExtensionInterface
{
private $coreExtension;

public function __construct()
{
$this->coreExtension = new CoreExtension();
@trigger_error(sprintf('league/commonmark-ext-autolink is deprecated; use %s from league/commonmark 1.3+ instead', CoreExtension::class), E_USER_DEPRECATED);
}

public function register(ConfigurableEnvironmentInterface $environment)
{
$environment->addEventListener(DocumentParsedEvent::class, new EmailAutolinkProcessor());
$environment->addEventListener(DocumentParsedEvent::class, new UrlAutolinkProcessor());
$this->coreExtension->register($environment);
}
}
63 changes: 13 additions & 50 deletions src/EmailAutolinkProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,67 +12,30 @@
namespace League\CommonMark\Ext\Autolink;

use League\CommonMark\Event\DocumentParsedEvent;
use League\CommonMark\Inline\Element\Link;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\Extension\Autolink\EmailAutolinkProcessor as CoreProcessor;

/**
* @deprecated The league/commonmark-ext-autolink extension is now deprecated. All functionality has been moved into league/commonmark 1.3+, so use that instead.
*/
final class EmailAutolinkProcessor
{
const REGEX = '/([A-Za-z0-9.\-_+]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_.]+)/';

private $coreProcessor;

public function __construct()
{
@trigger_error(sprintf('league/commonmark-ext-autolink is deprecated; use %s from league/commonmark 1.3+ instead', CoreProcessor::class), E_USER_DEPRECATED);
$this->coreProcessor = new CoreProcessor();
}

/**
* @param DocumentParsedEvent $e
*
* @return void
*/
public function __invoke(DocumentParsedEvent $e)
{
$walker = $e->getDocument()->walker();

while ($event = $walker->next()) {
$node = $event->getNode();
if ($node instanceof Text && !($node->parent() instanceof Link)) {
self::processAutolinks($node);
}
}
}

private static function processAutolinks(Text $node)
{
$contents = \preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE);

if (\count($contents) === 1) {
return;
}

$leftovers = '';
foreach ($contents as $i => $content) {
if ($i % 2 === 0) {
$text = $leftovers . $content;
if ($text !== '') {
$node->insertBefore(new Text($leftovers . $content));
}

$leftovers = '';
continue;
}

// Does the URL end with punctuation that should be stripped?
if (\substr($content, -1) === '.') {
// Add the punctuation later
$content = \substr($content, 0, -1);
$leftovers = '.';
}

// The last character cannot be - or _
if (\in_array(\substr($content, -1), ['-', '_'])) {
$node->insertBefore(new Text($content . $leftovers));
$leftovers = '';
continue;
}

$node->insertBefore(new Link('mailto:' . $content, $content));
}

$node->detach();
$this->coreProcessor->__invoke($e);
}
}
56 changes: 15 additions & 41 deletions src/InlineMentionParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,80 +11,54 @@

namespace League\CommonMark\Ext\Autolink;

use League\CommonMark\Inline\Element\Link;
use League\CommonMark\Extension\Autolink\InlineMentionParser as CoreParser;
use League\CommonMark\Inline\Parser\InlineParserInterface;
use League\CommonMark\InlineParserContext;

/**
* @deprecated The league/commonmark-ext-autolink extension is now deprecated. All functionality has been moved into league/commonmark 1.3+, so use that instead.
*/
final class InlineMentionParser implements InlineParserInterface
{
/** @var string */
private $linkPattern;

/** @var string */
private $handleRegex;
private $coreParser;

/**
* @param string $linkPattern
* @param string $handleRegex
*/
public function __construct($linkPattern, $handleRegex = '/^[A-Za-z0-9_]+(?!\w)/')
{
$this->linkPattern = $linkPattern;
$this->handleRegex = $handleRegex;
@trigger_error(sprintf('league/commonmark-ext-autolink is deprecated; use %s from league/commonmark 1.3+ instead', CoreParser::class), E_USER_DEPRECATED);
$this->coreParser = new CoreParser($linkPattern, $handleRegex);
}

/**
* {@inheritdoc}
*/
public function getCharacters(): array
{
return ['@'];
return $this->coreParser->getCharacters();
}

/**
* {@inheritdoc}
*/
public function parse(InlineParserContext $inlineContext): bool
{
$cursor = $inlineContext->getCursor();

// The @ symbol must not have any other characters immediately prior
$previousChar = $cursor->peek(-1);
if ($previousChar !== null && $previousChar !== ' ') {
// peek() doesn't modify the cursor, so no need to restore state first
return false;
}

// Save the cursor state in case we need to rewind and bail
$previousState = $cursor->saveState();

// Advance past the @ symbol to keep parsing simpler
$cursor->advance();

// Parse the handle
$handle = $cursor->match($this->handleRegex);
if (empty($handle)) {
// Regex failed to match; this isn't a valid Twitter handle
$cursor->restoreState($previousState);

return false;
}

$url = \sprintf($this->linkPattern, $handle);

$inlineContext->getContainer()->appendChild(new Link($url, '@' . $handle));

return true;
return $this->coreParser->parse($inlineContext);
}

public static function createTwitterHandleParser()
{
return new self('https://twitter.com/%s', '/^[A-Za-z0-9_]{1,15}(?!\w)/');
@trigger_error(sprintf('league/commonmark-ext-autolink is deprecated; use %s from league/commonmark 1.3+ instead', CoreParser::class), E_USER_DEPRECATED);

return CoreParser::createTwitterHandleParser();
}

public static function createGithubHandleParser()
{
// RegEx adapted from https://github.com/shinnn/github-username-regex/blob/master/index.js
return new self('https://www.github.com/%s', '/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)/');
@trigger_error(sprintf('league/commonmark-ext-autolink is deprecated; use %s from league/commonmark 1.3+ instead', CoreParser::class), E_USER_DEPRECATED);

return CoreParser::createGithubHandleParser();
}
}
102 changes: 8 additions & 94 deletions src/UrlAutolinkProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
namespace League\CommonMark\Ext\Autolink;

use League\CommonMark\Event\DocumentParsedEvent;
use League\CommonMark\Inline\Element\Link;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\Extension\Autolink\UrlAutolinkProcessor as CoreProcessor;

/**
* @deprecated The league/commonmark-ext-autolink extension is now deprecated. All functionality has been moved into league/commonmark 1.3+, so use that instead.
*/
final class UrlAutolinkProcessor
{
// RegEx adapted from https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/UrlValidator.php
Expand All @@ -41,11 +43,12 @@ final class UrlAutolinkProcessor
(?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional)
)~ixu';

private $finalRegex;
private $coreProcessor;

public function __construct(array $allowedProtocols = ['http', 'https', 'ftp'])
{
$this->finalRegex = \sprintf(self::REGEX, \implode('|', $allowedProtocols));
@trigger_error(sprintf('league/commonmark-ext-autolink is deprecated; use %s from league/commonmark 1.3+ instead', CoreProcessor::class), E_USER_DEPRECATED);
$this->coreProcessor = new CoreProcessor($allowedProtocols);
}

/**
Expand All @@ -55,95 +58,6 @@ public function __construct(array $allowedProtocols = ['http', 'https', 'ftp'])
*/
public function __invoke(DocumentParsedEvent $e)
{
$walker = $e->getDocument()->walker();

while ($event = $walker->next()) {
$node = $event->getNode();
if ($node instanceof Text && !($node->parent() instanceof Link)) {
self::processAutolinks($node, $this->finalRegex);
}
}
}

private static function processAutolinks(Text $node, $regex)
{
$contents = \preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE);

if (\count($contents) === 1) {
return;
}

$leftovers = '';
foreach ($contents as $i => $content) {
// Even-indexed elements are things before/after the URLs
if ($i % 2 === 0) {
// Insert any left-over characters here as well
$text = $leftovers . $content;
if ($text !== '') {
$node->insertBefore(new Text($leftovers . $content));
}

$leftovers = '';
continue;
}

$leftovers = '';

// Does the URL end with punctuation that should be stripped?
if (\preg_match('/(.+)([?!.,:*_~]+)$/', $content, $matches)) {
// Add the punctuation later
$content = $matches[1];
$leftovers = $matches[2];
}

// Does the URL end with something that looks like an entity reference?
if (\preg_match('/(.+)(&[A-Za-z0-9]+;)$/', $content, $matches)) {
$content = $matches[1];
$leftovers = $matches[2] . $leftovers;
}

// Does the URL need its closing paren chopped off?
if (\substr($content, -1) === ')' && self::hasMoreCloserParensThanOpeners($content)) {
$content = \substr($content, 0, -1);
$leftovers = ')' . $leftovers;
}

self::addLink($node, $content);
}

$node->detach();
}

private static function addLink(Text $node, $url)
{
// Auto-prefix 'http://' onto 'www' URLs
if (\substr($url, 0, 4) === 'www.') {
$node->insertBefore(new Link('http://' . $url, $url));

return;
}

$node->insertBefore(new Link($url, $url));
}

/**
* @param string $content
*
* @return bool
*/
private static function hasMoreCloserParensThanOpeners($content)
{
// Scan the entire autolink for the total number of parentheses.
// If there is a greater number of closing parentheses than opening ones,
// we don’t consider the last character part of the autolink, in order to
// facilitate including an autolink inside a parenthesis.
\preg_match_all('/[()]/', $content, $matches);

$charCount = ['(' => 0, ')' => 0];
foreach ($matches[0] as $char) {
$charCount[$char]++;
}

return $charCount[')'] > $charCount['('];
$this->coreProcessor->__invoke($e);
}
}

0 comments on commit 1e90bb2

Please sign in to comment.