1<?php 2 3/* 4 * This file is part of the league/commonmark package. 5 * 6 * (c) Colin O'Dell <colinodell@gmail.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace League\CommonMark\Extension\Autolink; 13 14use League\CommonMark\Event\DocumentParsedEvent; 15use League\CommonMark\Inline\Element\Link; 16use League\CommonMark\Inline\Element\Text; 17 18final class EmailAutolinkProcessor 19{ 20 const REGEX = '/([A-Za-z0-9.\-_+]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_.]+)/'; 21 22 /** 23 * @param DocumentParsedEvent $e 24 * 25 * @return void 26 */ 27 public function __invoke(DocumentParsedEvent $e) 28 { 29 $walker = $e->getDocument()->walker(); 30 31 while ($event = $walker->next()) { 32 $node = $event->getNode(); 33 if ($node instanceof Text && !($node->parent() instanceof Link)) { 34 self::processAutolinks($node); 35 } 36 } 37 } 38 39 private static function processAutolinks(Text $node): void 40 { 41 $contents = \preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); 42 43 if ($contents === false || \count($contents) === 1) { 44 return; 45 } 46 47 $leftovers = ''; 48 foreach ($contents as $i => $content) { 49 if ($i % 2 === 0) { 50 $text = $leftovers . $content; 51 if ($text !== '') { 52 $node->insertBefore(new Text($leftovers . $content)); 53 } 54 55 $leftovers = ''; 56 continue; 57 } 58 59 // Does the URL end with punctuation that should be stripped? 60 if (\substr($content, -1) === '.') { 61 // Add the punctuation later 62 $content = \substr($content, 0, -1); 63 $leftovers = '.'; 64 } 65 66 // The last character cannot be - or _ 67 if (\in_array(\substr($content, -1), ['-', '_'])) { 68 $node->insertBefore(new Text($content . $leftovers)); 69 $leftovers = ''; 70 continue; 71 } 72 73 $node->insertBefore(new Link('mailto:' . $content, $content)); 74 } 75 76 $node->detach(); 77 } 78} 79