Plugin Directory

Changeset 2149939


Ignore:
Timestamp:
09/03/2019 05:51:01 AM (7 years ago)
Author:
pbimal
Message:

File autoload conflict fix.
Parsedown replaced with latest release.

Location:
hosted-content-importer/trunk
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • hosted-content-importer/trunk/classes/hci/class.hosted_content_importer.inc.php

    r1434331 r2149939  
    115115    private function _autoload_processors($class_name = '')
    116116    {
    117         $processor = require_once(HCI_PLUGIN_DIR . "/classes/processors/class.{$class_name}.inc.php");
    118         if(is_file($processor))
    119         {
    120             require_once($processor);
    121         }
     117        if(file_exists(HCI_PLUGIN_DIR . "/classes/processors/class.{$class_name}.inc.php"))
     118        {
     119            $processor = require_once(HCI_PLUGIN_DIR . "/classes/processors/class.{$class_name}.inc.php");
     120            if(is_file($processor))
     121            {
     122                require_once($processor);
     123            }
     124        }
    122125    }
    123126}
  • hosted-content-importer/trunk/classes/parsedown/LICENSE.txt

    r1397630 r2149939  
    11The MIT License (MIT)
    22
    3 Copyright (c) 2013 Emanuil Rusev, erusev.com
     3Copyright (c) 2013-2018 Emanuil Rusev, erusev.com
    44
    55Permission is hereby granted, free of charge, to any person obtaining a copy of
  • hosted-content-importer/trunk/classes/parsedown/Parsedown.php

    r1412458 r2149939  
    1818    # ~
    1919
    20     const version = '1.6.0';
     20    const version = '1.8.0-beta-7';
    2121
    2222    # ~
    2323
    2424    function text($text)
     25    {
     26        $Elements = $this->textElements($text);
     27
     28        # convert to markup
     29        $markup = $this->elements($Elements);
     30
     31        # trim line breaks
     32        $markup = trim($markup, "\n");
     33
     34        return $markup;
     35    }
     36
     37    protected function textElements($text)
    2538    {
    2639        # make sure no definitions are set
     
    3750
    3851        # iterate through lines to identify blocks
    39         $markup = $this->lines($lines);
    40 
    41         # trim line breaks
    42         $markup = trim($markup, "\n");
    43 
    44         return $markup;
     52        return $this->linesElements($lines);
    4553    }
    4654
     
    7583
    7684    protected $urlsLinked = true;
     85
     86    function setSafeMode($safeMode)
     87    {
     88        $this->safeMode = (bool) $safeMode;
     89
     90        return $this;
     91    }
     92
     93    protected $safeMode;
     94
     95    function setStrictMode($strictMode)
     96    {
     97        $this->strictMode = (bool) $strictMode;
     98
     99        return $this;
     100    }
     101
     102    protected $strictMode;
     103
     104    protected $safeLinksWhitelist = array(
     105        'http://',
     106        'https://',
     107        'ftp://',
     108        'ftps://',
     109        'mailto:',
     110        'tel:',
     111        'data:image/png;base64,',
     112        'data:image/gif;base64,',
     113        'data:image/jpeg;base64,',
     114        'irc:',
     115        'ircs:',
     116        'git:',
     117        'ssh:',
     118        'news:',
     119        'steam:',
     120    );
    77121
    78122    #
     
    118162    protected function lines(array $lines)
    119163    {
     164        return $this->elements($this->linesElements($lines));
     165    }
     166
     167    protected function linesElements(array $lines)
     168    {
     169        $Elements = array();
    120170        $CurrentBlock = null;
    121171
     
    126176                if (isset($CurrentBlock))
    127177                {
    128                     $CurrentBlock['interrupted'] = true;
     178                    $CurrentBlock['interrupted'] = (isset($CurrentBlock['interrupted'])
     179                        ? $CurrentBlock['interrupted'] + 1 : 1
     180                    );
    129181                }
    130182
     
    132184            }
    133185
    134             if (strpos($line, "\t") !== false)
    135             {
    136                 $parts = explode("\t", $line);
    137 
    138                 $line = $parts[0];
    139 
    140                 unset($parts[0]);
    141 
    142                 foreach ($parts as $part)
    143                 {
    144                     $shortage = 4 - mb_strlen($line, 'utf-8') % 4;
    145 
    146                     $line .= str_repeat(' ', $shortage);
    147                     $line .= $part;
    148                 }
    149             }
    150 
    151             $indent = 0;
    152 
    153             while (isset($line[$indent]) and $line[$indent] === ' ')
    154             {
    155                 $indent ++;
    156             }
     186            while (($beforeTab = strstr($line, "\t", true)) !== false)
     187            {
     188                $shortage = 4 - mb_strlen($beforeTab, 'utf-8') % 4;
     189
     190                $line = $beforeTab
     191                    . str_repeat(' ', $shortage)
     192                    . substr($line, strlen($beforeTab) + 1)
     193                ;
     194            }
     195
     196            $indent = strspn($line, ' ');
    157197
    158198            $text = $indent > 0 ? substr($line, $indent) : $line;
     
    166206            if (isset($CurrentBlock['continuable']))
    167207            {
    168                 $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);
     208                $methodName = 'block' . $CurrentBlock['type'] . 'Continue';
     209                $Block = $this->$methodName($Line, $CurrentBlock);
    169210
    170211                if (isset($Block))
     
    178219                    if ($this->isBlockCompletable($CurrentBlock['type']))
    179220                    {
    180                         $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
     221                        $methodName = 'block' . $CurrentBlock['type'] . 'Complete';
     222                        $CurrentBlock = $this->$methodName($CurrentBlock);
    181223                    }
    182224                }
     
    204246            foreach ($blockTypes as $blockType)
    205247            {
    206                 $Block = $this->{'block'.$blockType}($Line, $CurrentBlock);
     248                $Block = $this->{"block$blockType"}($Line, $CurrentBlock);
    207249
    208250                if (isset($Block))
     
    212254                    if ( ! isset($Block['identified']))
    213255                    {
    214                         $Blocks []= $CurrentBlock;
     256                        if (isset($CurrentBlock))
     257                        {
     258                            $Elements[] = $this->extractElement($CurrentBlock);
     259                        }
    215260
    216261                        $Block['identified'] = true;
     
    230275            # ~
    231276
    232             if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))
    233             {
    234                 $CurrentBlock['element']['text'] .= "\n".$text;
     277            if (isset($CurrentBlock) and $CurrentBlock['type'] === 'Paragraph')
     278            {
     279                $Block = $this->paragraphContinue($Line, $CurrentBlock);
     280            }
     281
     282            if (isset($Block))
     283            {
     284                $CurrentBlock = $Block;
    235285            }
    236286            else
    237287            {
    238                 $Blocks []= $CurrentBlock;
     288                if (isset($CurrentBlock))
     289                {
     290                    $Elements[] = $this->extractElement($CurrentBlock);
     291                }
    239292
    240293                $CurrentBlock = $this->paragraph($Line);
     
    248301        if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type']))
    249302        {
    250             $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
     303            $methodName = 'block' . $CurrentBlock['type'] . 'Complete';
     304            $CurrentBlock = $this->$methodName($CurrentBlock);
    251305        }
    252306
    253307        # ~
    254308
    255         $Blocks []= $CurrentBlock;
    256 
    257         unset($Blocks[0]);
     309        if (isset($CurrentBlock))
     310        {
     311            $Elements[] = $this->extractElement($CurrentBlock);
     312        }
    258313
    259314        # ~
    260315
    261         $markup = '';
    262 
    263         foreach ($Blocks as $Block)
    264         {
    265             if (isset($Block['hidden']))
    266             {
    267                 continue;
    268             }
    269 
    270             $markup .= "\n";
    271             $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
    272         }
    273 
    274         $markup .= "\n";
    275 
    276         # ~
    277 
    278         return $markup;
     316        return $Elements;
     317    }
     318
     319    protected function extractElement(array $Component)
     320    {
     321        if ( ! isset($Component['element']))
     322        {
     323            if (isset($Component['markup']))
     324            {
     325                $Component['element'] = array('rawHtml' => $Component['markup']);
     326            }
     327            elseif (isset($Component['hidden']))
     328            {
     329                $Component['element'] = array();
     330            }
     331        }
     332
     333        return $Component['element'];
    279334    }
    280335
    281336    protected function isBlockContinuable($Type)
    282337    {
    283         return method_exists($this, 'block'.$Type.'Continue');
     338        return method_exists($this, 'block' . $Type . 'Continue');
    284339    }
    285340
    286341    protected function isBlockCompletable($Type)
    287342    {
    288         return method_exists($this, 'block'.$Type.'Complete');
     343        return method_exists($this, 'block' . $Type . 'Complete');
    289344    }
    290345
     
    294349    protected function blockCode($Line, $Block = null)
    295350    {
    296         if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))
     351        if (isset($Block) and $Block['type'] === 'Paragraph' and ! isset($Block['interrupted']))
    297352        {
    298353            return;
     
    306361                'element' => array(
    307362                    'name' => 'pre',
    308                     'handler' => 'element',
    309                     'text' => array(
     363                    'element' => array(
    310364                        'name' => 'code',
    311365                        'text' => $text,
     
    324378            if (isset($Block['interrupted']))
    325379            {
    326                 $Block['element']['text']['text'] .= "\n";
     380                $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']);
    327381
    328382                unset($Block['interrupted']);
    329383            }
    330384
    331             $Block['element']['text']['text'] .= "\n";
     385            $Block['element']['element']['text'] .= "\n";
    332386
    333387            $text = substr($Line['body'], 4);
    334388
    335             $Block['element']['text']['text'] .= $text;
     389            $Block['element']['element']['text'] .= $text;
    336390
    337391            return $Block;
     
    341395    protected function blockCodeComplete($Block)
    342396    {
    343         $text = $Block['element']['text']['text'];
    344 
    345         $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
    346 
    347         $Block['element']['text']['text'] = $text;
    348 
    349397        return $Block;
    350398    }
     
    355403    protected function blockComment($Line)
    356404    {
    357         if ($this->markupEscaped)
    358         {
    359             return;
    360         }
    361 
    362         if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
    363         {
    364             $Block = array(
    365                 'markup' => $Line['body'],
    366             );
    367 
    368             if (preg_match('/-->$/', $Line['text']))
    369             {
    370                 $Block['closed'] = true;
    371             }
    372 
    373             return $Block;
    374         }
    375     }
    376 
    377     protected function blockCommentContinue($Line, array $Block)
    378     {
    379         if (isset($Block['closed']))
    380         {
    381             return;
    382         }
    383 
    384         $Block['markup'] .= "\n" . $Line['body'];
    385 
    386         if (preg_match('/-->$/', $Line['text']))
    387         {
    388             $Block['closed'] = true;
    389         }
    390 
    391         return $Block;
    392     }
    393 
    394     #
    395     # Fenced Code
    396 
    397     protected function blockFencedCode($Line)
    398     {
    399         if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches))
    400         {
    401             $Element = array(
    402                 'name' => 'code',
    403                 'text' => '',
    404             );
    405 
    406             if (isset($matches[1]))
    407             {
    408                 $class = 'language-'.$matches[1];
    409 
    410                 $Element['attributes'] = array(
    411                     'class' => $class,
    412                 );
    413             }
    414 
    415             $Block = array(
    416                 'char' => $Line['text'][0],
    417                 'element' => array(
    418                     'name' => 'pre',
    419                     'handler' => 'element',
    420                     'text' => $Element,
    421                 ),
    422             );
    423 
    424             return $Block;
    425         }
    426     }
    427 
    428     protected function blockFencedCodeContinue($Line, $Block)
    429     {
    430         if (isset($Block['complete']))
    431         {
    432             return;
    433         }
    434 
    435         if (isset($Block['interrupted']))
    436         {
    437             $Block['element']['text']['text'] .= "\n";
    438 
    439             unset($Block['interrupted']);
    440         }
    441 
    442         if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
    443         {
    444             $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);
    445 
    446             $Block['complete'] = true;
    447 
    448             return $Block;
    449         }
    450 
    451         $Block['element']['text']['text'] .= "\n".$Line['body'];;
    452 
    453         return $Block;
    454     }
    455 
    456     protected function blockFencedCodeComplete($Block)
    457     {
    458         $text = $Block['element']['text']['text'];
    459 
    460         $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
    461 
    462         $Block['element']['text']['text'] = $text;
    463 
    464         return $Block;
    465     }
    466 
    467     #
    468     # Header
    469 
    470     protected function blockHeader($Line)
    471     {
    472         if (isset($Line['text'][1]))
    473         {
    474             $level = 1;
    475 
    476             while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
    477             {
    478                 $level ++;
    479             }
    480 
    481             if ($level > 6)
    482             {
    483                 return;
    484             }
    485 
    486             $text = trim($Line['text'], '# ');
    487 
     405        if ($this->markupEscaped or $this->safeMode)
     406        {
     407            return;
     408        }
     409
     410        if (strpos($Line['text'], '<!--') === 0)
     411        {
    488412            $Block = array(
    489413                'element' => array(
    490                     'name' => 'h' . min(6, $level),
    491                     'text' => $text,
    492                     'handler' => 'line',
     414                    'rawHtml' => $Line['body'],
     415                    'autobreak' => true,
    493416                ),
    494417            );
    495418
     419            if (strpos($Line['text'], '-->') !== false)
     420            {
     421                $Block['closed'] = true;
     422            }
     423
    496424            return $Block;
    497425        }
    498426    }
    499427
     428    protected function blockCommentContinue($Line, array $Block)
     429    {
     430        if (isset($Block['closed']))
     431        {
     432            return;
     433        }
     434
     435        $Block['element']['rawHtml'] .= "\n" . $Line['body'];
     436
     437        if (strpos($Line['text'], '-->') !== false)
     438        {
     439            $Block['closed'] = true;
     440        }
     441
     442        return $Block;
     443    }
     444
     445    #
     446    # Fenced Code
     447
     448    protected function blockFencedCode($Line)
     449    {
     450        $marker = $Line['text'][0];
     451
     452        $openerLength = strspn($Line['text'], $marker);
     453
     454        if ($openerLength < 3)
     455        {
     456            return;
     457        }
     458
     459        $infostring = trim(substr($Line['text'], $openerLength), "\t ");
     460
     461        if (strpos($infostring, '`') !== false)
     462        {
     463            return;
     464        }
     465
     466        $Element = array(
     467            'name' => 'code',
     468            'text' => '',
     469        );
     470
     471        if ($infostring !== '')
     472        {
     473            /**
     474             * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes
     475             * Every HTML element may have a class attribute specified.
     476             * The attribute, if specified, must have a value that is a set
     477             * of space-separated tokens representing the various classes
     478             * that the element belongs to.
     479             * [...]
     480             * The space characters, for the purposes of this specification,
     481             * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab),
     482             * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and
     483             * U+000D CARRIAGE RETURN (CR).
     484             */
     485            $language = substr($infostring, 0, strcspn($infostring, " \t\n\f\r"));
     486
     487            $Element['attributes'] = array('class' => "language-$language");
     488        }
     489
     490        $Block = array(
     491            'char' => $marker,
     492            'openerLength' => $openerLength,
     493            'element' => array(
     494                'name' => 'pre',
     495                'element' => $Element,
     496            ),
     497        );
     498
     499        return $Block;
     500    }
     501
     502    protected function blockFencedCodeContinue($Line, $Block)
     503    {
     504        if (isset($Block['complete']))
     505        {
     506            return;
     507        }
     508
     509        if (isset($Block['interrupted']))
     510        {
     511            $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']);
     512
     513            unset($Block['interrupted']);
     514        }
     515
     516        if (($len = strspn($Line['text'], $Block['char'])) >= $Block['openerLength']
     517            and chop(substr($Line['text'], $len), ' ') === ''
     518        ) {
     519            $Block['element']['element']['text'] = substr($Block['element']['element']['text'], 1);
     520
     521            $Block['complete'] = true;
     522
     523            return $Block;
     524        }
     525
     526        $Block['element']['element']['text'] .= "\n" . $Line['body'];
     527
     528        return $Block;
     529    }
     530
     531    protected function blockFencedCodeComplete($Block)
     532    {
     533        return $Block;
     534    }
     535
     536    #
     537    # Header
     538
     539    protected function blockHeader($Line)
     540    {
     541        $level = strspn($Line['text'], '#');
     542
     543        if ($level > 6)
     544        {
     545            return;
     546        }
     547
     548        $text = trim($Line['text'], '#');
     549
     550        if ($this->strictMode and isset($text[0]) and $text[0] !== ' ')
     551        {
     552            return;
     553        }
     554
     555        $text = trim($text, ' ');
     556
     557        $Block = array(
     558            'element' => array(
     559                'name' => 'h' . $level,
     560                'handler' => array(
     561                    'function' => 'lineElements',
     562                    'argument' => $text,
     563                    'destination' => 'elements',
     564                )
     565            ),
     566        );
     567
     568        return $Block;
     569    }
     570
    500571    #
    501572    # List
    502573
    503     protected function blockList($Line)
    504     {
    505         list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
    506 
    507         if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))
    508         {
     574    protected function blockList($Line, array $CurrentBlock = null)
     575    {
     576        list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]{1,9}+[.\)]');
     577
     578        if (preg_match('/^('.$pattern.'([ ]++|$))(.*+)/', $Line['text'], $matches))
     579        {
     580            $contentIndent = strlen($matches[2]);
     581
     582            if ($contentIndent >= 5)
     583            {
     584                $contentIndent -= 1;
     585                $matches[1] = substr($matches[1], 0, -$contentIndent);
     586                $matches[3] = str_repeat(' ', $contentIndent) . $matches[3];
     587            }
     588            elseif ($contentIndent === 0)
     589            {
     590                $matches[1] .= ' ';
     591            }
     592
     593            $markerWithoutWhitespace = strstr($matches[1], ' ', true);
     594
    509595            $Block = array(
    510596                'indent' => $Line['indent'],
    511597                'pattern' => $pattern,
     598                'data' => array(
     599                    'type' => $name,
     600                    'marker' => $matches[1],
     601                    'markerType' => ($name === 'ul' ? $markerWithoutWhitespace : substr($markerWithoutWhitespace, -1)),
     602                ),
    512603                'element' => array(
    513604                    'name' => $name,
    514                     'handler' => 'elements',
     605                    'elements' => array(),
    515606                ),
    516607            );
     608            $Block['data']['markerTypeRegex'] = preg_quote($Block['data']['markerType'], '/');
     609
     610            if ($name === 'ol')
     611            {
     612                $listStart = ltrim(strstr($matches[1], $Block['data']['markerType'], true), '0') ?: '0';
     613
     614                if ($listStart !== '1')
     615                {
     616                    if (
     617                        isset($CurrentBlock)
     618                        and $CurrentBlock['type'] === 'Paragraph'
     619                        and ! isset($CurrentBlock['interrupted'])
     620                    ) {
     621                        return;
     622                    }
     623
     624                    $Block['element']['attributes'] = array('start' => $listStart);
     625                }
     626            }
    517627
    518628            $Block['li'] = array(
    519629                'name' => 'li',
    520                 'handler' => 'li',
    521                 'text' => array(
    522                     $matches[2],
    523                 ),
    524             );
    525 
    526             $Block['element']['text'] []= & $Block['li'];
     630                'handler' => array(
     631                    'function' => 'li',
     632                    'argument' => !empty($matches[3]) ? array($matches[3]) : array(),
     633                    'destination' => 'elements'
     634                )
     635            );
     636
     637            $Block['element']['elements'] []= & $Block['li'];
    527638
    528639            return $Block;
     
    532643    protected function blockListContinue($Line, array $Block)
    533644    {
    534         if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))
    535         {
     645        if (isset($Block['interrupted']) and empty($Block['li']['handler']['argument']))
     646        {
     647            return null;
     648        }
     649
     650        $requiredIndent = ($Block['indent'] + strlen($Block['data']['marker']));
     651
     652        if ($Line['indent'] < $requiredIndent
     653            and (
     654                (
     655                    $Block['data']['type'] === 'ol'
     656                    and preg_match('/^[0-9]++'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches)
     657                ) or (
     658                    $Block['data']['type'] === 'ul'
     659                    and preg_match('/^'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches)
     660                )
     661            )
     662        ) {
    536663            if (isset($Block['interrupted']))
    537664            {
    538                 $Block['li']['text'] []= '';
     665                $Block['li']['handler']['argument'] []= '';
     666
     667                $Block['loose'] = true;
    539668
    540669                unset($Block['interrupted']);
     
    544673
    545674            $text = isset($matches[1]) ? $matches[1] : '';
     675
     676            $Block['indent'] = $Line['indent'];
    546677
    547678            $Block['li'] = array(
    548679                'name' => 'li',
    549                 'handler' => 'li',
    550                 'text' => array(
    551                     $text,
    552                 ),
    553             );
    554 
    555             $Block['element']['text'] []= & $Block['li'];
     680                'handler' => array(
     681                    'function' => 'li',
     682                    'argument' => array($text),
     683                    'destination' => 'elements'
     684                )
     685            );
     686
     687            $Block['element']['elements'] []= & $Block['li'];
    556688
    557689            return $Block;
    558690        }
     691        elseif ($Line['indent'] < $requiredIndent and $this->blockList($Line))
     692        {
     693            return null;
     694        }
    559695
    560696        if ($Line['text'][0] === '[' and $this->blockReference($Line))
     
    563699        }
    564700
     701        if ($Line['indent'] >= $requiredIndent)
     702        {
     703            if (isset($Block['interrupted']))
     704            {
     705                $Block['li']['handler']['argument'] []= '';
     706
     707                $Block['loose'] = true;
     708
     709                unset($Block['interrupted']);
     710            }
     711
     712            $text = substr($Line['body'], $requiredIndent);
     713
     714            $Block['li']['handler']['argument'] []= $text;
     715
     716            return $Block;
     717        }
     718
    565719        if ( ! isset($Block['interrupted']))
    566720        {
    567             $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
    568 
    569             $Block['li']['text'] []= $text;
     721            $text = preg_replace('/^[ ]{0,'.$requiredIndent.'}+/', '', $Line['body']);
     722
     723            $Block['li']['handler']['argument'] []= $text;
    570724
    571725            return $Block;
    572726        }
    573 
    574         if ($Line['indent'] > 0)
    575         {
    576             $Block['li']['text'] []= '';
    577 
    578             $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
    579 
    580             $Block['li']['text'] []= $text;
    581 
    582             unset($Block['interrupted']);
    583 
    584             return $Block;
    585         }
     727    }
     728
     729    protected function blockListComplete(array $Block)
     730    {
     731        if (isset($Block['loose']))
     732        {
     733            foreach ($Block['element']['elements'] as &$li)
     734            {
     735                if (end($li['handler']['argument']) !== '')
     736                {
     737                    $li['handler']['argument'] []= '';
     738                }
     739            }
     740        }
     741
     742        return $Block;
    586743    }
    587744
     
    591748    protected function blockQuote($Line)
    592749    {
    593         if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
     750        if (preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches))
    594751        {
    595752            $Block = array(
    596753                'element' => array(
    597754                    'name' => 'blockquote',
    598                     'handler' => 'lines',
    599                     'text' => (array) $matches[1],
     755                    'handler' => array(
     756                        'function' => 'linesElements',
     757                        'argument' => (array) $matches[1],
     758                        'destination' => 'elements',
     759                    )
    600760                ),
    601761            );
     
    607767    protected function blockQuoteContinue($Line, array $Block)
    608768    {
    609         if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
    610         {
    611             if (isset($Block['interrupted']))
    612             {
    613                 $Block['element']['text'] []= '';
    614 
    615                 unset($Block['interrupted']);
    616             }
    617 
    618             $Block['element']['text'] []= $matches[1];
     769        if (isset($Block['interrupted']))
     770        {
     771            return;
     772        }
     773
     774        if ($Line['text'][0] === '>' and preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches))
     775        {
     776            $Block['element']['handler']['argument'] []= $matches[1];
    619777
    620778            return $Block;
     
    623781        if ( ! isset($Block['interrupted']))
    624782        {
    625             $Block['element']['text'] []= $Line['text'];
     783            $Block['element']['handler']['argument'] []= $Line['text'];
    626784
    627785            return $Block;
     
    634792    protected function blockRule($Line)
    635793    {
    636         if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text']))
     794        $marker = $Line['text'][0];
     795
     796        if (substr_count($Line['text'], $marker) >= 3 and chop($Line['text'], " $marker") === '')
    637797        {
    638798            $Block = array(
    639799                'element' => array(
    640                     'name' => 'hr'
     800                    'name' => 'hr',
    641801                ),
    642802            );
     
    651811    protected function blockSetextHeader($Line, array $Block = null)
    652812    {
    653         if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
    654         {
    655             return;
    656         }
    657 
    658         if (chop($Line['text'], $Line['text'][0]) === '')
     813        if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted']))
     814        {
     815            return;
     816        }
     817
     818        if ($Line['indent'] < 4 and chop(chop($Line['text'], ' '), $Line['text'][0]) === '')
    659819        {
    660820            $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
     
    669829    protected function blockMarkup($Line)
    670830    {
    671         if ($this->markupEscaped)
    672         {
    673             return;
    674         }
    675 
    676         if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
     831        if ($this->markupEscaped or $this->safeMode)
     832        {
     833            return;
     834        }
     835
     836        if (preg_match('/^<[\/]?+(\w*)(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+(\/)?>/', $Line['text'], $matches))
    677837        {
    678838            $element = strtolower($matches[1]);
     
    685845            $Block = array(
    686846                'name' => $matches[1],
    687                 'depth' => 0,
    688                 'markup' => $Line['text'],
    689             );
    690 
    691             $length = strlen($matches[0]);
    692 
    693             $remainder = substr($Line['text'], $length);
    694 
    695             if (trim($remainder) === '')
    696             {
    697                 if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
    698                 {
    699                     $Block['closed'] = true;
    700 
    701                     $Block['void'] = true;
    702                 }
    703             }
    704             else
    705             {
    706                 if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
    707                 {
    708                     return;
    709                 }
    710 
    711                 if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
    712                 {
    713                     $Block['closed'] = true;
    714                 }
    715             }
     847                'element' => array(
     848                    'rawHtml' => $Line['text'],
     849                    'autobreak' => true,
     850                ),
     851            );
    716852
    717853            return $Block;
     
    721857    protected function blockMarkupContinue($Line, array $Block)
    722858    {
    723         if (isset($Block['closed']))
    724         {
    725             return;
    726         }
    727 
    728         if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
    729         {
    730             $Block['depth'] ++;
    731         }
    732 
    733         if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
    734         {
    735             if ($Block['depth'] > 0)
    736             {
    737                 $Block['depth'] --;
    738             }
    739             else
    740             {
    741                 $Block['closed'] = true;
    742             }
    743         }
    744 
    745         if (isset($Block['interrupted']))
    746         {
    747             $Block['markup'] .= "\n";
    748 
    749             unset($Block['interrupted']);
    750         }
    751 
    752         $Block['markup'] .= "\n".$Line['body'];
     859        if (isset($Block['closed']) or isset($Block['interrupted']))
     860        {
     861            return;
     862        }
     863
     864        $Block['element']['rawHtml'] .= "\n" . $Line['body'];
    753865
    754866        return $Block;
     
    760872    protected function blockReference($Line)
    761873    {
    762         if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
    763         {
     874        if (strpos($Line['text'], ']') !== false
     875            and preg_match('/^\[(.+?)\]:[ ]*+<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*+$/', $Line['text'], $matches)
     876        ) {
    764877            $id = strtolower($matches[1]);
    765878
    766879            $Data = array(
    767880                'url' => $matches[2],
    768                 'title' => null,
    769             );
    770 
    771             if (isset($matches[3]))
    772             {
    773                 $Data['title'] = $matches[3];
    774             }
     881                'title' => isset($matches[3]) ? $matches[3] : null,
     882            );
    775883
    776884            $this->DefinitionData['Reference'][$id] = $Data;
    777885
    778886            $Block = array(
    779                 'hidden' => true,
     887                'element' => array(),
    780888            );
    781889
     
    789897    protected function blockTable($Line, array $Block = null)
    790898    {
    791         if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
    792         {
    793             return;
    794         }
    795 
    796         if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')
    797         {
    798             $alignments = array();
    799 
    800             $divider = $Line['text'];
    801 
    802             $divider = trim($divider);
    803             $divider = trim($divider, '|');
    804 
    805             $dividerCells = explode('|', $divider);
    806 
    807             foreach ($dividerCells as $dividerCell)
    808             {
    809                 $dividerCell = trim($dividerCell);
    810 
    811                 if ($dividerCell === '')
    812                 {
    813                     continue;
    814                 }
    815 
    816                 $alignment = null;
    817 
    818                 if ($dividerCell[0] === ':')
    819                 {
    820                     $alignment = 'left';
    821                 }
    822 
    823                 if (substr($dividerCell, - 1) === ':')
    824                 {
    825                     $alignment = $alignment === 'left' ? 'center' : 'right';
    826                 }
    827 
    828                 $alignments []= $alignment;
    829             }
    830 
    831             # ~
    832 
    833             $HeaderElements = array();
    834 
    835             $header = $Block['element']['text'];
    836 
    837             $header = trim($header);
    838             $header = trim($header, '|');
    839 
    840             $headerCells = explode('|', $header);
    841 
    842             foreach ($headerCells as $index => $headerCell)
    843             {
    844                 $headerCell = trim($headerCell);
    845 
    846                 $HeaderElement = array(
    847                     'name' => 'th',
    848                     'text' => $headerCell,
    849                     'handler' => 'line',
     899        if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted']))
     900        {
     901            return;
     902        }
     903
     904        if (
     905            strpos($Block['element']['handler']['argument'], '|') === false
     906            and strpos($Line['text'], '|') === false
     907            and strpos($Line['text'], ':') === false
     908            or strpos($Block['element']['handler']['argument'], "\n") !== false
     909        ) {
     910            return;
     911        }
     912
     913        if (chop($Line['text'], ' -:|') !== '')
     914        {
     915            return;
     916        }
     917
     918        $alignments = array();
     919
     920        $divider = $Line['text'];
     921
     922        $divider = trim($divider);
     923        $divider = trim($divider, '|');
     924
     925        $dividerCells = explode('|', $divider);
     926
     927        foreach ($dividerCells as $dividerCell)
     928        {
     929            $dividerCell = trim($dividerCell);
     930
     931            if ($dividerCell === '')
     932            {
     933                return;
     934            }
     935
     936            $alignment = null;
     937
     938            if ($dividerCell[0] === ':')
     939            {
     940                $alignment = 'left';
     941            }
     942
     943            if (substr($dividerCell, - 1) === ':')
     944            {
     945                $alignment = $alignment === 'left' ? 'center' : 'right';
     946            }
     947
     948            $alignments []= $alignment;
     949        }
     950
     951        # ~
     952
     953        $HeaderElements = array();
     954
     955        $header = $Block['element']['handler']['argument'];
     956
     957        $header = trim($header);
     958        $header = trim($header, '|');
     959
     960        $headerCells = explode('|', $header);
     961
     962        if (count($headerCells) !== count($alignments))
     963        {
     964            return;
     965        }
     966
     967        foreach ($headerCells as $index => $headerCell)
     968        {
     969            $headerCell = trim($headerCell);
     970
     971            $HeaderElement = array(
     972                'name' => 'th',
     973                'handler' => array(
     974                    'function' => 'lineElements',
     975                    'argument' => $headerCell,
     976                    'destination' => 'elements',
     977                )
     978            );
     979
     980            if (isset($alignments[$index]))
     981            {
     982                $alignment = $alignments[$index];
     983
     984                $HeaderElement['attributes'] = array(
     985                    'style' => "text-align: $alignment;",
    850986                );
    851 
    852                 if (isset($alignments[$index]))
    853                 {
    854                     $alignment = $alignments[$index];
    855 
    856                     $HeaderElement['attributes'] = array(
    857                         'style' => 'text-align: '.$alignment.';',
    858                     );
    859                 }
    860 
    861                 $HeaderElements []= $HeaderElement;
    862             }
    863 
    864             # ~
    865 
    866             $Block = array(
    867                 'alignments' => $alignments,
    868                 'identified' => true,
    869                 'element' => array(
    870                     'name' => 'table',
    871                     'handler' => 'elements',
    872                 ),
    873             );
    874 
    875             $Block['element']['text'] []= array(
    876                 'name' => 'thead',
    877                 'handler' => 'elements',
    878             );
    879 
    880             $Block['element']['text'] []= array(
    881                 'name' => 'tbody',
    882                 'handler' => 'elements',
    883                 'text' => array(),
    884             );
    885 
    886             $Block['element']['text'][0]['text'] []= array(
    887                 'name' => 'tr',
    888                 'handler' => 'elements',
    889                 'text' => $HeaderElements,
    890             );
    891 
    892             return $Block;
    893         }
     987            }
     988
     989            $HeaderElements []= $HeaderElement;
     990        }
     991
     992        # ~
     993
     994        $Block = array(
     995            'alignments' => $alignments,
     996            'identified' => true,
     997            'element' => array(
     998                'name' => 'table',
     999                'elements' => array(),
     1000            ),
     1001        );
     1002
     1003        $Block['element']['elements'] []= array(
     1004            'name' => 'thead',
     1005        );
     1006
     1007        $Block['element']['elements'] []= array(
     1008            'name' => 'tbody',
     1009            'elements' => array(),
     1010        );
     1011
     1012        $Block['element']['elements'][0]['elements'] []= array(
     1013            'name' => 'tr',
     1014            'elements' => $HeaderElements,
     1015        );
     1016
     1017        return $Block;
    8941018    }
    8951019
     
    9011025        }
    9021026
    903         if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))
     1027        if (count($Block['alignments']) === 1 or $Line['text'][0] === '|' or strpos($Line['text'], '|'))
    9041028        {
    9051029            $Elements = array();
     
    9101034            $row = trim($row, '|');
    9111035
    912             preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
    913 
    914             foreach ($matches[0] as $index => $cell)
     1036            preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]++`|`)++/', $row, $matches);
     1037
     1038            $cells = array_slice($matches[0], 0, count($Block['alignments']));
     1039
     1040            foreach ($cells as $index => $cell)
    9151041            {
    9161042                $cell = trim($cell);
     
    9181044                $Element = array(
    9191045                    'name' => 'td',
    920                     'handler' => 'line',
    921                     'text' => $cell,
     1046                    'handler' => array(
     1047                        'function' => 'lineElements',
     1048                        'argument' => $cell,
     1049                        'destination' => 'elements',
     1050                    )
    9221051                );
    9231052
     
    9251054                {
    9261055                    $Element['attributes'] = array(
    927                         'style' => 'text-align: '.$Block['alignments'][$index].';',
     1056                        'style' => 'text-align: ' . $Block['alignments'][$index] . ';',
    9281057                    );
    9291058                }
     
    9341063            $Element = array(
    9351064                'name' => 'tr',
    936                 'handler' => 'elements',
    937                 'text' => $Elements,
    938             );
    939 
    940             $Block['element']['text'][1]['text'] []= $Element;
     1065                'elements' => $Elements,
     1066            );
     1067
     1068            $Block['element']['elements'][1]['elements'] []= $Element;
    9411069
    9421070            return $Block;
     
    9501078    protected function paragraph($Line)
    9511079    {
    952         $Block = array(
     1080        return array(
     1081            'type' => 'Paragraph',
    9531082            'element' => array(
    9541083                'name' => 'p',
    955                 'text' => $Line['text'],
    956                 'handler' => 'line',
     1084                'handler' => array(
     1085                    'function' => 'lineElements',
     1086                    'argument' => $Line['text'],
     1087                    'destination' => 'elements',
     1088                ),
    9571089            ),
    9581090        );
     1091    }
     1092
     1093    protected function paragraphContinue($Line, array $Block)
     1094    {
     1095        if (isset($Block['interrupted']))
     1096        {
     1097            return;
     1098        }
     1099
     1100        $Block['element']['handler']['argument'] .= "\n".$Line['text'];
    9591101
    9601102        return $Block;
     
    9661108
    9671109    protected $InlineTypes = array(
    968         '"' => array('SpecialCharacter'),
    9691110        '!' => array('Image'),
    9701111        '&' => array('SpecialCharacter'),
    9711112        '*' => array('Emphasis'),
    9721113        ':' => array('Url'),
    973         '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
    974         '>' => array('SpecialCharacter'),
     1114        '<' => array('UrlTag', 'EmailTag', 'Markup'),
    9751115        '[' => array('Link'),
    9761116        '_' => array('Emphasis'),
     
    9821122    # ~
    9831123
    984     protected $inlineMarkerList = '!"*_&[:<>`~\\';
     1124    protected $inlineMarkerList = '!*_&[:<`~\\';
    9851125
    9861126    #
     
    9881128    #
    9891129
    990     public function line($text)
    991     {
    992         $markup = '';
     1130    public function line($text, $nonNestables = array())
     1131    {
     1132        return $this->elements($this->lineElements($text, $nonNestables));
     1133    }
     1134
     1135    protected function lineElements($text, $nonNestables = array())
     1136    {
     1137        # standardize line breaks
     1138        $text = str_replace(array("\r\n", "\r"), "\n", $text);
     1139
     1140        $Elements = array();
     1141
     1142        $nonNestables = (empty($nonNestables)
     1143            ? array()
     1144            : array_combine($nonNestables, $nonNestables)
     1145        );
    9931146
    9941147        # $excerpt is based on the first occurrence of a marker
     
    9981151            $marker = $excerpt[0];
    9991152
    1000             $markerPosition = strpos($text, $marker);
     1153            $markerPosition = strlen($text) - strlen($excerpt);
    10011154
    10021155            $Excerpt = array('text' => $excerpt, 'context' => $text);
     
    10041157            foreach ($this->InlineTypes[$marker] as $inlineType)
    10051158            {
    1006                 $Inline = $this->{'inline'.$inlineType}($Excerpt);
     1159                # check to see if the current inline type is nestable in the current context
     1160
     1161                if (isset($nonNestables[$inlineType]))
     1162                {
     1163                    continue;
     1164                }
     1165
     1166                $Inline = $this->{"inline$inlineType"}($Excerpt);
    10071167
    10081168                if ( ! isset($Inline))
     
    10251185                }
    10261186
     1187                # cause the new element to 'inherit' our non nestables
     1188
     1189
     1190                $Inline['element']['nonNestables'] = isset($Inline['element']['nonNestables'])
     1191                    ? array_merge($Inline['element']['nonNestables'], $nonNestables)
     1192                    : $nonNestables
     1193                ;
     1194
    10271195                # the text that comes before the inline
    10281196                $unmarkedText = substr($text, 0, $Inline['position']);
    10291197
    10301198                # compile the unmarked text
    1031                 $markup .= $this->unmarkedText($unmarkedText);
     1199                $InlineText = $this->inlineText($unmarkedText);
     1200                $Elements[] = $InlineText['element'];
    10321201
    10331202                # compile the inline
    1034                 $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
     1203                $Elements[] = $this->extractElement($Inline);
    10351204
    10361205                # remove the examined text
     
    10441213            $unmarkedText = substr($text, 0, $markerPosition + 1);
    10451214
    1046             $markup .= $this->unmarkedText($unmarkedText);
     1215            $InlineText = $this->inlineText($unmarkedText);
     1216            $Elements[] = $InlineText['element'];
    10471217
    10481218            $text = substr($text, $markerPosition + 1);
    10491219        }
    10501220
    1051         $markup .= $this->unmarkedText($text);
    1052 
    1053         return $markup;
     1221        $InlineText = $this->inlineText($text);
     1222        $Elements[] = $InlineText['element'];
     1223
     1224        foreach ($Elements as &$Element)
     1225        {
     1226            if ( ! isset($Element['autobreak']))
     1227            {
     1228                $Element['autobreak'] = false;
     1229            }
     1230        }
     1231
     1232        return $Elements;
    10541233    }
    10551234
     
    10581237    #
    10591238
     1239    protected function inlineText($text)
     1240    {
     1241        $Inline = array(
     1242            'extent' => strlen($text),
     1243            'element' => array(),
     1244        );
     1245
     1246        $Inline['element']['elements'] = self::pregReplaceElements(
     1247            $this->breaksEnabled ? '/[ ]*+\n/' : '/(?:[ ]*+\\\\|[ ]{2,}+)\n/',
     1248            array(
     1249                array('name' => 'br'),
     1250                array('text' => "\n"),
     1251            ),
     1252            $text
     1253        );
     1254
     1255        return $Inline;
     1256    }
     1257
    10601258    protected function inlineCode($Excerpt)
    10611259    {
    10621260        $marker = $Excerpt['text'][0];
    10631261
    1064         if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
     1262        if (preg_match('/^(['.$marker.']++)[ ]*+(.+?)[ ]*+(?<!['.$marker.'])\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
    10651263        {
    10661264            $text = $matches[2];
    1067             $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
    1068             $text = preg_replace("/[ ]*\n/", ' ', $text);
     1265            $text = preg_replace('/[ ]*+\n/', ' ', $text);
    10691266
    10701267            return array(
     
    10801277    protected function inlineEmailTag($Excerpt)
    10811278    {
    1082         if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
    1083         {
     1279        $hostnameLabel = '[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?';
     1280
     1281        $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]++@'
     1282            . $hostnameLabel . '(?:\.' . $hostnameLabel . ')*';
     1283
     1284        if (strpos($Excerpt['text'], '>') !== false
     1285            and preg_match("/^<((mailto:)?$commonMarkEmail)>/i", $Excerpt['text'], $matches)
     1286        ){
    10841287            $url = $matches[1];
    10851288
    10861289            if ( ! isset($matches[2]))
    10871290            {
    1088                 $url = 'mailto:' . $url;
     1291                $url = "mailto:$url";
    10891292            }
    10901293
     
    11281331            'element' => array(
    11291332                'name' => $emphasis,
    1130                 'handler' => 'line',
    1131                 'text' => $matches[1],
     1333                'handler' => array(
     1334                    'function' => 'lineElements',
     1335                    'argument' => $matches[1],
     1336                    'destination' => 'elements',
     1337                )
    11321338            ),
    11331339        );
     
    11391345        {
    11401346            return array(
    1141                 'markup' => $Excerpt['text'][1],
     1347                'element' => array('rawHtml' => $Excerpt['text'][1]),
    11421348                'extent' => 2,
    11431349            );
     
    11671373                'attributes' => array(
    11681374                    'src' => $Link['element']['attributes']['href'],
    1169                     'alt' => $Link['element']['text'],
     1375                    'alt' => $Link['element']['handler']['argument'],
    11701376                ),
     1377                'autobreak' => true,
    11711378            ),
    11721379        );
     
    11831390        $Element = array(
    11841391            'name' => 'a',
    1185             'handler' => 'line',
    1186             'text' => null,
     1392            'handler' => array(
     1393                'function' => 'lineElements',
     1394                'argument' => null,
     1395                'destination' => 'elements',
     1396            ),
     1397            'nonNestables' => array('Url', 'Link'),
    11871398            'attributes' => array(
    11881399                'href' => null,
     
    11951406        $remainder = $Excerpt['text'];
    11961407
    1197         if (preg_match('/\[((?:[^][]|(?R))*)\]/', $remainder, $matches))
    1198         {
    1199             $Element['text'] = $matches[1];
     1408        if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
     1409        {
     1410            $Element['handler']['argument'] = $matches[1];
    12001411
    12011412            $extent += strlen($matches[0]);
     
    12081419        }
    12091420
    1210         if (preg_match('/^[(]((?:[^ ()]|[(][^ )]+[)])+)(?:[ ]+("[^"]*"|\'[^\']*\'))?[)]/', $remainder, $matches))
     1421        if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*+"|\'[^\']*+\'))?\s*+[)]/', $remainder, $matches))
    12111422        {
    12121423            $Element['attributes']['href'] = $matches[1];
     
    12231434            if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
    12241435            {
    1225                 $definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
     1436                $definition = strlen($matches[1]) ? $matches[1] : $Element['handler']['argument'];
    12261437                $definition = strtolower($definition);
    12271438
     
    12301441            else
    12311442            {
    1232                 $definition = strtolower($Element['text']);
     1443                $definition = strtolower($Element['handler']['argument']);
    12331444            }
    12341445
     
    12431454            $Element['attributes']['title'] = $Definition['title'];
    12441455        }
    1245 
    1246         $Element['attributes']['href'] = str_replace(array('&', '<'), array('&amp;', '&lt;'), $Element['attributes']['href']);
    12471456
    12481457        return array(
     
    12541463    protected function inlineMarkup($Excerpt)
    12551464    {
    1256         if ($this->markupEscaped or strpos($Excerpt['text'], '>') === false)
    1257         {
    1258             return;
    1259         }
    1260 
    1261         if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w*[ ]*>/s', $Excerpt['text'], $matches))
     1465        if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false)
     1466        {
     1467            return;
     1468        }
     1469
     1470        if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*+[ ]*+>/s', $Excerpt['text'], $matches))
    12621471        {
    12631472            return array(
    1264                 'markup' => $matches[0],
     1473                'element' => array('rawHtml' => $matches[0]),
    12651474                'extent' => strlen($matches[0]),
    12661475            );
    12671476        }
    12681477
    1269         if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches))
     1478        if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?+[^-])*-->/s', $Excerpt['text'], $matches))
    12701479        {
    12711480            return array(
    1272                 'markup' => $matches[0],
     1481                'element' => array('rawHtml' => $matches[0]),
    12731482                'extent' => strlen($matches[0]),
    12741483            );
    12751484        }
    12761485
    1277         if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
     1486        if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*+(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+\/?>/s', $Excerpt['text'], $matches))
    12781487        {
    12791488            return array(
    1280                 'markup' => $matches[0],
     1489                'element' => array('rawHtml' => $matches[0]),
    12811490                'extent' => strlen($matches[0]),
    12821491            );
     
    12861495    protected function inlineSpecialCharacter($Excerpt)
    12871496    {
    1288         if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text']))
    1289         {
     1497        if (substr($Excerpt['text'], 1, 1) !== ' ' and strpos($Excerpt['text'], ';') !== false
     1498            and preg_match('/^&(#?+[0-9a-zA-Z]++);/', $Excerpt['text'], $matches)
     1499        ) {
    12901500            return array(
    1291                 'markup' => '&amp;',
    1292                 'extent' => 1,
    1293             );
    1294         }
    1295 
    1296         $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
    1297 
    1298         if (isset($SpecialCharacter[$Excerpt['text'][0]]))
    1299         {
    1300             return array(
    1301                 'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
    1302                 'extent' => 1,
    1303             );
    1304         }
     1501                'element' => array('rawHtml' => '&' . $matches[1] . ';'),
     1502                'extent' => strlen($matches[0]),
     1503            );
     1504        }
     1505
     1506        return;
    13051507    }
    13061508
     
    13181520                'element' => array(
    13191521                    'name' => 'del',
    1320                     'text' => $matches[1],
    1321                     'handler' => 'line',
     1522                    'handler' => array(
     1523                        'function' => 'lineElements',
     1524                        'argument' => $matches[1],
     1525                        'destination' => 'elements',
     1526                    )
    13221527                ),
    13231528            );
     
    13321537        }
    13331538
    1334         if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
    1335         {
     1539        if (strpos($Excerpt['context'], 'http') !== false
     1540            and preg_match('/\bhttps?+:[\/]{2}[^\s<]+\b\/*+/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)
     1541        ) {
     1542            $url = $matches[0][0];
     1543
    13361544            $Inline = array(
    13371545                'extent' => strlen($matches[0][0]),
     
    13391547                'element' => array(
    13401548                    'name' => 'a',
    1341                     'text' => $matches[0][0],
     1549                    'text' => $url,
    13421550                    'attributes' => array(
    1343                         'href' => $matches[0][0],
     1551                        'href' => $url,
    13441552                    ),
    13451553                ),
     
    13521560    protected function inlineUrlTag($Excerpt)
    13531561    {
    1354         if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
    1355         {
    1356             $url = str_replace(array('&', '<'), array('&amp;', '&lt;'), $matches[1]);
     1562        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w++:\/{2}[^ >]++)>/i', $Excerpt['text'], $matches))
     1563        {
     1564            $url = $matches[1];
    13571565
    13581566            return array(
     
    13731581    protected function unmarkedText($text)
    13741582    {
    1375         if ($this->breaksEnabled)
    1376         {
    1377             $text = preg_replace('/[ ]*\n/', "<br />\n", $text);
     1583        $Inline = $this->inlineText($text);
     1584        return $this->element($Inline['element']);
     1585    }
     1586
     1587    #
     1588    # Handlers
     1589    #
     1590
     1591    protected function handle(array $Element)
     1592    {
     1593        if (isset($Element['handler']))
     1594        {
     1595            if (!isset($Element['nonNestables']))
     1596            {
     1597                $Element['nonNestables'] = array();
     1598            }
     1599
     1600            if (is_string($Element['handler']))
     1601            {
     1602                $function = $Element['handler'];
     1603                $argument = $Element['text'];
     1604                unset($Element['text']);
     1605                $destination = 'rawHtml';
     1606            }
     1607            else
     1608            {
     1609                $function = $Element['handler']['function'];
     1610                $argument = $Element['handler']['argument'];
     1611                $destination = $Element['handler']['destination'];
     1612            }
     1613
     1614            $Element[$destination] = $this->{$function}($argument, $Element['nonNestables']);
     1615
     1616            if ($destination === 'handler')
     1617            {
     1618                $Element = $this->handle($Element);
     1619            }
     1620
     1621            unset($Element['handler']);
     1622        }
     1623
     1624        return $Element;
     1625    }
     1626
     1627    protected function handleElementRecursive(array $Element)
     1628    {
     1629        return $this->elementApplyRecursive(array($this, 'handle'), $Element);
     1630    }
     1631
     1632    protected function handleElementsRecursive(array $Elements)
     1633    {
     1634        return $this->elementsApplyRecursive(array($this, 'handle'), $Elements);
     1635    }
     1636
     1637    protected function elementApplyRecursive($closure, array $Element)
     1638    {
     1639        $Element = call_user_func($closure, $Element);
     1640
     1641        if (isset($Element['elements']))
     1642        {
     1643            $Element['elements'] = $this->elementsApplyRecursive($closure, $Element['elements']);
     1644        }
     1645        elseif (isset($Element['element']))
     1646        {
     1647            $Element['element'] = $this->elementApplyRecursive($closure, $Element['element']);
     1648        }
     1649
     1650        return $Element;
     1651    }
     1652
     1653    protected function elementApplyRecursiveDepthFirst($closure, array $Element)
     1654    {
     1655        if (isset($Element['elements']))
     1656        {
     1657            $Element['elements'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['elements']);
     1658        }
     1659        elseif (isset($Element['element']))
     1660        {
     1661            $Element['element'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['element']);
     1662        }
     1663
     1664        $Element = call_user_func($closure, $Element);
     1665
     1666        return $Element;
     1667    }
     1668
     1669    protected function elementsApplyRecursive($closure, array $Elements)
     1670    {
     1671        foreach ($Elements as &$Element)
     1672        {
     1673            $Element = $this->elementApplyRecursive($closure, $Element);
     1674        }
     1675
     1676        return $Elements;
     1677    }
     1678
     1679    protected function elementsApplyRecursiveDepthFirst($closure, array $Elements)
     1680    {
     1681        foreach ($Elements as &$Element)
     1682        {
     1683            $Element = $this->elementApplyRecursiveDepthFirst($closure, $Element);
     1684        }
     1685
     1686        return $Elements;
     1687    }
     1688
     1689    protected function element(array $Element)
     1690    {
     1691        if ($this->safeMode)
     1692        {
     1693            $Element = $this->sanitiseElement($Element);
     1694        }
     1695
     1696        # identity map if element has no handler
     1697        $Element = $this->handle($Element);
     1698
     1699        $hasName = isset($Element['name']);
     1700
     1701        $markup = '';
     1702
     1703        if ($hasName)
     1704        {
     1705            $markup .= '<' . $Element['name'];
     1706
     1707            if (isset($Element['attributes']))
     1708            {
     1709                foreach ($Element['attributes'] as $name => $value)
     1710                {
     1711                    if ($value === null)
     1712                    {
     1713                        continue;
     1714                    }
     1715
     1716                    $markup .= " $name=\"".self::escape($value).'"';
     1717                }
     1718            }
     1719        }
     1720
     1721        $permitRawHtml = false;
     1722
     1723        if (isset($Element['text']))
     1724        {
     1725            $text = $Element['text'];
     1726        }
     1727        // very strongly consider an alternative if you're writing an
     1728        // extension
     1729        elseif (isset($Element['rawHtml']))
     1730        {
     1731            $text = $Element['rawHtml'];
     1732
     1733            $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode'];
     1734            $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
     1735        }
     1736
     1737        $hasContent = isset($text) || isset($Element['element']) || isset($Element['elements']);
     1738
     1739        if ($hasContent)
     1740        {
     1741            $markup .= $hasName ? '>' : '';
     1742
     1743            if (isset($Element['elements']))
     1744            {
     1745                $markup .= $this->elements($Element['elements']);
     1746            }
     1747            elseif (isset($Element['element']))
     1748            {
     1749                $markup .= $this->element($Element['element']);
     1750            }
     1751            else
     1752            {
     1753                if (!$permitRawHtml)
     1754                {
     1755                    $markup .= self::escape($text, true);
     1756                }
     1757                else
     1758                {
     1759                    $markup .= $text;
     1760                }
     1761            }
     1762
     1763            $markup .= $hasName ? '</' . $Element['name'] . '>' : '';
     1764        }
     1765        elseif ($hasName)
     1766        {
     1767            $markup .= ' />';
     1768        }
     1769
     1770        return $markup;
     1771    }
     1772
     1773    protected function elements(array $Elements)
     1774    {
     1775        $markup = '';
     1776
     1777        $autoBreak = true;
     1778
     1779        foreach ($Elements as $Element)
     1780        {
     1781            if (empty($Element))
     1782            {
     1783                continue;
     1784            }
     1785
     1786            $autoBreakNext = (isset($Element['autobreak'])
     1787                ? $Element['autobreak'] : isset($Element['name'])
     1788            );
     1789            // (autobreak === false) covers both sides of an element
     1790            $autoBreak = !$autoBreak ? $autoBreak : $autoBreakNext;
     1791
     1792            $markup .= ($autoBreak ? "\n" : '') . $this->element($Element);
     1793            $autoBreak = $autoBreakNext;
     1794        }
     1795
     1796        $markup .= $autoBreak ? "\n" : '';
     1797
     1798        return $markup;
     1799    }
     1800
     1801    # ~
     1802
     1803    protected function li($lines)
     1804    {
     1805        $Elements = $this->linesElements($lines);
     1806
     1807        if ( ! in_array('', $lines)
     1808            and isset($Elements[0]) and isset($Elements[0]['name'])
     1809            and $Elements[0]['name'] === 'p'
     1810        ) {
     1811            unset($Elements[0]['name']);
     1812        }
     1813
     1814        return $Elements;
     1815    }
     1816
     1817    #
     1818    # AST Convenience
     1819    #
     1820
     1821    /**
     1822     * Replace occurrences $regexp with $Elements in $text. Return an array of
     1823     * elements representing the replacement.
     1824     */
     1825    protected static function pregReplaceElements($regexp, $Elements, $text)
     1826    {
     1827        $newElements = array();
     1828
     1829        while (preg_match($regexp, $text, $matches, PREG_OFFSET_CAPTURE))
     1830        {
     1831            $offset = $matches[0][1];
     1832            $before = substr($text, 0, $offset);
     1833            $after = substr($text, $offset + strlen($matches[0][0]));
     1834
     1835            $newElements[] = array('text' => $before);
     1836
     1837            foreach ($Elements as $Element)
     1838            {
     1839                $newElements[] = $Element;
     1840            }
     1841
     1842            $text = $after;
     1843        }
     1844
     1845        $newElements[] = array('text' => $text);
     1846
     1847        return $newElements;
     1848    }
     1849
     1850    #
     1851    # Deprecated Methods
     1852    #
     1853
     1854    function parse($text)
     1855    {
     1856        $markup = $this->text($text);
     1857
     1858        return $markup;
     1859    }
     1860
     1861    protected function sanitiseElement(array $Element)
     1862    {
     1863        static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';
     1864        static $safeUrlNameToAtt  = array(
     1865            'a'   => 'href',
     1866            'img' => 'src',
     1867        );
     1868
     1869        if ( ! isset($Element['name']))
     1870        {
     1871            unset($Element['attributes']);
     1872            return $Element;
     1873        }
     1874
     1875        if (isset($safeUrlNameToAtt[$Element['name']]))
     1876        {
     1877            $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
     1878        }
     1879
     1880        if ( ! empty($Element['attributes']))
     1881        {
     1882            foreach ($Element['attributes'] as $att => $val)
     1883            {
     1884                # filter out badly parsed attribute
     1885                if ( ! preg_match($goodAttribute, $att))
     1886                {
     1887                    unset($Element['attributes'][$att]);
     1888                }
     1889                # dump onevent attribute
     1890                elseif (self::striAtStart($att, 'on'))
     1891                {
     1892                    unset($Element['attributes'][$att]);
     1893                }
     1894            }
     1895        }
     1896
     1897        return $Element;
     1898    }
     1899
     1900    protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
     1901    {
     1902        foreach ($this->safeLinksWhitelist as $scheme)
     1903        {
     1904            if (self::striAtStart($Element['attributes'][$attribute], $scheme))
     1905            {
     1906                return $Element;
     1907            }
     1908        }
     1909
     1910        $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);
     1911
     1912        return $Element;
     1913    }
     1914
     1915    #
     1916    # Static Methods
     1917    #
     1918
     1919    protected static function escape($text, $allowQuotes = false)
     1920    {
     1921        return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
     1922    }
     1923
     1924    protected static function striAtStart($string, $needle)
     1925    {
     1926        $len = strlen($needle);
     1927
     1928        if ($len > strlen($string))
     1929        {
     1930            return false;
    13781931        }
    13791932        else
    13801933        {
    1381             $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "<br />\n", $text);
    1382             $text = str_replace(" \n", "\n", $text);
    1383         }
    1384 
    1385         return $text;
    1386     }
    1387 
    1388     #
    1389     # Handlers
    1390     #
    1391 
    1392     protected function element(array $Element)
    1393     {
    1394         $markup = '<'.$Element['name'];
    1395 
    1396         if (isset($Element['attributes']))
    1397         {
    1398             foreach ($Element['attributes'] as $name => $value)
    1399             {
    1400                 if ($value === null)
    1401                 {
    1402                     continue;
    1403                 }
    1404 
    1405                 $markup .= ' '.$name.'="'.$value.'"';
    1406             }
    1407         }
    1408 
    1409         if (isset($Element['text']))
    1410         {
    1411             $markup .= '>';
    1412 
    1413             if (isset($Element['handler']))
    1414             {
    1415                 $markup .= $this->{$Element['handler']}($Element['text']);
    1416             }
    1417             else
    1418             {
    1419                 $markup .= $Element['text'];
    1420             }
    1421 
    1422             $markup .= '</'.$Element['name'].'>';
    1423         }
    1424         else
    1425         {
    1426             $markup .= ' />';
    1427         }
    1428 
    1429         return $markup;
    1430     }
    1431 
    1432     protected function elements(array $Elements)
    1433     {
    1434         $markup = '';
    1435 
    1436         foreach ($Elements as $Element)
    1437         {
    1438             $markup .= "\n" . $this->element($Element);
    1439         }
    1440 
    1441         $markup .= "\n";
    1442 
    1443         return $markup;
    1444     }
    1445 
    1446     # ~
    1447 
    1448     protected function li($lines)
    1449     {
    1450         $markup = $this->lines($lines);
    1451 
    1452         $trimmedMarkup = trim($markup);
    1453 
    1454         if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>')
    1455         {
    1456             $markup = $trimmedMarkup;
    1457             $markup = substr($markup, 3);
    1458 
    1459             $position = strpos($markup, "</p>");
    1460 
    1461             $markup = substr_replace($markup, '', $position, 4);
    1462         }
    1463 
    1464         return $markup;
    1465     }
    1466 
    1467     #
    1468     # Deprecated Methods
    1469     #
    1470 
    1471     function parse($text)
    1472     {
    1473         $markup = $this->text($text);
    1474 
    1475         return $markup;
    1476     }
    1477 
    1478     #
    1479     # Static Methods
    1480     #
     1934            return strtolower(substr($string, 0, $len)) === strtolower($needle);
     1935        }
     1936    }
    14811937
    14821938    static function instance($name = 'default')
     
    15061962
    15071963    protected $specialCharacters = array(
    1508         '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',
     1964        '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', '~'
    15091965    );
    15101966
    15111967    protected $StrongRegex = array(
    1512         '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
    1513         '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',
     1968        '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*+[*])+?)[*]{2}(?![*])/s',
     1969        '_' => '/^__((?:\\\\_|[^_]|_[^_]*+_)+?)__(?!_)/us',
    15141970    );
    15151971
     
    15191975    );
    15201976
    1521     protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?';
     1977    protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*+(?:\s*+=\s*+(?:[^"\'=<>`\s]+|"[^"]*+"|\'[^\']*+\'))?+';
    15221978
    15231979    protected $voidElements = array(
     
    15301986        'i', 'rp', 'del', 'code',          'strike', 'marquee',
    15311987        'q', 'rt', 'ins', 'font',          'strong',
    1532         's', 'tt', 'sub', 'mark',
    1533         'u', 'xm', 'sup', 'nobr',
    1534                    'var', 'ruby',
    1535                    'wbr', 'span',
    1536                          'time',
     1988        's', 'tt', 'kbd', 'mark',
     1989        'u', 'xm', 'sub', 'nobr',
     1990                   'sup', 'ruby',
     1991                   'var', 'span',
     1992                   'wbr', 'time',
    15371993    );
    15381994}
  • hosted-content-importer/trunk/hosted-content-importer.php

    r1434331 r2149939  
    33 * Plugin Name: Hosted Content Importer (HCI)
    44 * Plugin URI: https://wordpress.org/plugins/hosted-content-importer/
    5  * Description: Embeds third party contents. Usage: <code>[third source="markdown" id="URL" section=""]</code>
     5 * Description: Embeds third party contents within your blog. Usage: <code>[third source="markdown" id="URL" section=""]</code>.
    66 * Author: Bimal Poudel
    77 * Author URI: http://bimal.org.np/
    8  * Development URI: https://github.com/bimalpoudel/hosted-content-importer/
    9  * License: GPLv2 or later
    10  * Version: 3.0.1
     8 * Development URI: https://github.com/anytizer/hosted-content-importer.wp/
     9 * License: MIT
     10 * Version: 3.0.2
    1111 */
    1212
     
    1414 * Cached file validity duration: seconds(Hour+Minutes+Seconds)
    1515 */
    16 define('HCI_CACHE_DURATION', 5 * 60 * 60 + 0 * 60 + 0);
     16define("HCI_CACHE_DURATION", 5 * 60 * 60 + 0 * 60 + 0);
    1717
    1818/**
    1919 * Do NOT edit
    2020 */
    21 define('HCI_PLUGIN_DIR', dirname(__FILE__));
     21define("HCI_PLUGIN_DIR", dirname(__FILE__));
    2222
    2323/**
     
    2525 * https://github.com/erusev/parsedown
    2626 */
    27 if(!class_exists('Parsedown'))
     27if(!class_exists("Parsedown"))
    2828{
    29     require_once(HCI_PLUGIN_DIR . '/classes/parsedown/Parsedown.php');
     29    require_once HCI_PLUGIN_DIR . "/classes/parsedown/Parsedown.php";
    3030}
    3131
     
    3333 * Main binder
    3434 */
    35 require_once(HCI_PLUGIN_DIR . '/classes/hci/interface.hosted_content_interface.inc.php');
    36 require_once(HCI_PLUGIN_DIR . '/classes/hci/class.hosted_content_importer.inc.php');
     35require_once HCI_PLUGIN_DIR . "/classes/hci/interface.hosted_content_interface.inc.php";
     36require_once HCI_PLUGIN_DIR . "/classes/hci/class.hosted_content_importer.inc.php";
    3737
    3838/**
    39  * Install WordPress Shortcodes Handler
    40  * Install report page
    41  * Install menus
     39 * Installs WordPress Shortcodes Handler
     40 * Installs report page
     41 * Installs menus
    4242 */
    43 require_once(HCI_PLUGIN_DIR . '/classes/hci/class.hosted_content_shortcode.inc.php');
     43require_once HCI_PLUGIN_DIR . "/classes/hci/class.hosted_content_shortcode.inc.php";
    4444new hosted_content_shortcode();
  • hosted-content-importer/trunk/readme.txt

    r1814939 r2149939  
    22
    33Contributors: pbimal
    4 Donate link: http://bimal.org.np/
     4Donate Link: http://bimal.org.np/
    55Tags: cached, content, embed, external, gist, hci, hosted, import, markdown, remote, shortcode, third
    6 Requires at least: 4.5.0
    7 Tested up to: 4.9.2
     6Requires at least: 4.0.0
     7Tested up to: 4.9.5
    88Stable tag: 3.0.1
    99License: GPLv3 or later
     
    1616== Description ==
    1717
    18 It imports third party hosted contents within WordPress blog texts. You define from which url/resource to fetch the content. The source may be editable by anyone else whom you trust. Thus, it logically empowers you to allow other users to externally edit a particular section of your blogs. And, you do not have to give them any access to your website.
     18It imports third party hosted contents within WordPress blog. You can define from which url/resource to fetch the content. The original source may be editable by anyone else whom you trust. Thus, it logically empowers you to allow other users to externally edit a particular section of your blogs. And, you do not have to give them any access credentials of your website.
    1919
    2020After installation, use shortcode tag `[third]` with few parameters as:
    2121
    2222`[third source="markdown" id="https://goo.gl/UpclKH" section=""]`
     23
     24 * `source` is a content processor type.
     25 * `id` is a URL or ID given by the third parties.
     26 * `section` is an optional parameter to access deeper content.
     27 * `cache` is a boolean directive whether to reuse the cached content.
     28
    2329
    2430It will then embed remote markdown content inside your blog.
     
    7985`[third source="file" id="/tmp/readme.txt" section=""]`
    8086
    81 It hast to be a static file for security reasons. For example, if you read the .php file, it will NOT process it, rather read its contents only. Your can contain valid HTML data, css and javascripts.
     87It has to be a static file for security reasons. For example, if you read the .php file, it will NOT process it, rather read its contents only. Your can contain valid HTML data, css and javascripts.
    8288
    8389
     
    209215Please view the original development at: https://goo.gl/89KgSC for details and further plans.
    210216
     217= 3.0.2 =
     218* Parsedown upgraded.
     219* Typos corrections.
     220
    211221= 3.0.1 =
    212 * TinyMCE Plugin and text mode tags inserter added.
     222* TinyMCE Plugin and text mode editor plgins added.
    213223* As-Is request for not wrapping the HTML Output within HCI divs.
    214224* Experimental: Dumped handlers or registered shortcodes.
Note: See TracChangeset for help on using the changeset viewer.