Update parsedown & parsedown-extra for php-7
This commit is contained in:
parent
f35c631ae5
commit
d1b7b3e46d
File diff suppressed because it is too large
Load Diff
@ -15,20 +15,27 @@
|
|||||||
|
|
||||||
class ParsedownExtra extends Parsedown
|
class ParsedownExtra extends Parsedown
|
||||||
{
|
{
|
||||||
#
|
# ~
|
||||||
|
|
||||||
|
const version = '0.7.0';
|
||||||
|
|
||||||
# ~
|
# ~
|
||||||
|
|
||||||
function __construct()
|
function __construct()
|
||||||
{
|
{
|
||||||
$this->BlockTypes[':'] []= 'DefinitionList';
|
if (parent::version < '1.5.0')
|
||||||
|
{
|
||||||
|
throw new Exception('ParsedownExtra requires a later version of Parsedown');
|
||||||
|
}
|
||||||
|
|
||||||
$this->DefinitionTypes['*'] []= 'Abbreviation';
|
$this->BlockTypes[':'] []= 'DefinitionList';
|
||||||
|
$this->BlockTypes['*'] []= 'Abbreviation';
|
||||||
|
|
||||||
# identify footnote definitions before reference definitions
|
# identify footnote definitions before reference definitions
|
||||||
array_unshift($this->DefinitionTypes['['], 'Footnote');
|
array_unshift($this->BlockTypes['['], 'Footnote');
|
||||||
|
|
||||||
# identify footnote markers before before links
|
# identify footnote markers before before links
|
||||||
array_unshift($this->SpanTypes['['], 'FootnoteMarker');
|
array_unshift($this->InlineTypes['['], 'FootnoteMarker');
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -44,7 +51,7 @@ class ParsedownExtra extends Parsedown
|
|||||||
|
|
||||||
# add footnotes
|
# add footnotes
|
||||||
|
|
||||||
if (isset($this->Definitions['Footnote']))
|
if (isset($this->DefinitionData['Footnote']))
|
||||||
{
|
{
|
||||||
$Element = $this->buildFootnoteElement();
|
$Element = $this->buildFootnoteElement();
|
||||||
|
|
||||||
@ -59,20 +66,70 @@ class ParsedownExtra extends Parsedown
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Atx
|
# Abbreviation
|
||||||
|
|
||||||
protected function identifyAtx($Line)
|
protected function blockAbbreviation($Line)
|
||||||
{
|
{
|
||||||
$Block = parent::identifyAtx($Line);
|
if (preg_match('/^\*\[(.+?)\]:[ ]*(.+?)[ ]*$/', $Line['text'], $matches))
|
||||||
|
|
||||||
if (preg_match('/[ ]*'.$this->attributesPattern.'[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE))
|
|
||||||
{
|
{
|
||||||
$attributeString = $matches[1][0];
|
$this->DefinitionData['Abbreviation'][$matches[1]] = $matches[2];
|
||||||
|
|
||||||
$Block['element']['attributes'] = $this->parseAttributes($attributeString);
|
$Block = array(
|
||||||
|
'hidden' => true,
|
||||||
|
);
|
||||||
|
|
||||||
$Block['element']['text'] = substr($Block['element']['text'], 0, $matches[0][1]);
|
return $Block;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Footnote
|
||||||
|
|
||||||
|
protected function blockFootnote($Line)
|
||||||
|
{
|
||||||
|
if (preg_match('/^\[\^(.+?)\]:[ ]?(.*)$/', $Line['text'], $matches))
|
||||||
|
{
|
||||||
|
$Block = array(
|
||||||
|
'label' => $matches[1],
|
||||||
|
'text' => $matches[2],
|
||||||
|
'hidden' => true,
|
||||||
|
);
|
||||||
|
|
||||||
|
return $Block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function blockFootnoteContinue($Line, $Block)
|
||||||
|
{
|
||||||
|
if ($Line['text'][0] === '[' and preg_match('/^\[\^(.+?)\]:/', $Line['text']))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($Block['interrupted']))
|
||||||
|
{
|
||||||
|
if ($Line['indent'] >= 4)
|
||||||
|
{
|
||||||
|
$Block['text'] .= "\n\n" . $Line['text'];
|
||||||
|
|
||||||
|
return $Block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$Block['text'] .= "\n" . $Line['text'];
|
||||||
|
|
||||||
|
return $Block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function blockFootnoteComplete($Block)
|
||||||
|
{
|
||||||
|
$this->DefinitionData['Footnote'][$Block['label']] = array(
|
||||||
|
'text' => $Block['text'],
|
||||||
|
'count' => null,
|
||||||
|
'number' => null,
|
||||||
|
);
|
||||||
|
|
||||||
return $Block;
|
return $Block;
|
||||||
}
|
}
|
||||||
@ -80,9 +137,9 @@ class ParsedownExtra extends Parsedown
|
|||||||
#
|
#
|
||||||
# Definition List
|
# Definition List
|
||||||
|
|
||||||
protected function identifyDefinitionList($Line, $Block)
|
protected function blockDefinitionList($Line, $Block)
|
||||||
{
|
{
|
||||||
if (isset($Block['type']))
|
if ( ! isset($Block) or isset($Block['type']))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -104,54 +161,56 @@ class ParsedownExtra extends Parsedown
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$Element['text'] []= array(
|
|
||||||
'name' => 'dd',
|
|
||||||
'handler' => 'line',
|
|
||||||
'text' => ltrim($Line['text'], ' :'),
|
|
||||||
);
|
|
||||||
|
|
||||||
$Block['element'] = $Element;
|
$Block['element'] = $Element;
|
||||||
|
|
||||||
|
$Block = $this->addDdElement($Line, $Block);
|
||||||
|
|
||||||
return $Block;
|
return $Block;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function addToDefinitionList($Line, array $Block)
|
protected function blockDefinitionListContinue($Line, array $Block)
|
||||||
{
|
{
|
||||||
if ($Line['text'][0] === ':')
|
if ($Line['text'][0] === ':')
|
||||||
{
|
{
|
||||||
$Block['element']['text'] []= array(
|
$Block = $this->addDdElement($Line, $Block);
|
||||||
'name' => 'dd',
|
|
||||||
'handler' => 'line',
|
|
||||||
'text' => ltrim($Line['text'], ' :'),
|
|
||||||
);
|
|
||||||
|
|
||||||
return $Block;
|
return $Block;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if ( ! isset($Block['interrupted']))
|
|
||||||
{
|
{
|
||||||
$Element = array_pop($Block['element']['text']);
|
if (isset($Block['interrupted']) and $Line['indent'] === 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$Element['text'] .= "\n" . chop($Line['text']);
|
if (isset($Block['interrupted']))
|
||||||
|
{
|
||||||
|
$Block['dd']['handler'] = 'text';
|
||||||
|
$Block['dd']['text'] .= "\n\n";
|
||||||
|
|
||||||
$Block['element']['text'] []= $Element;
|
unset($Block['interrupted']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = substr($Line['body'], min($Line['indent'], 4));
|
||||||
|
|
||||||
|
$Block['dd']['text'] .= "\n" . $text;
|
||||||
|
|
||||||
return $Block;
|
return $Block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Setext
|
# Header
|
||||||
|
|
||||||
protected function identifySetext($Line, array $Block = null)
|
protected function blockHeader($Line)
|
||||||
{
|
{
|
||||||
$Block = parent::identifySetext($Line, $Block);
|
$Block = parent::blockHeader($Line);
|
||||||
|
|
||||||
if (preg_match('/[ ]*'.$this->attributesPattern.'[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE))
|
if (preg_match('/[ #]*{('.$this->regexAttribute.'+)}[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE))
|
||||||
{
|
{
|
||||||
$attributeString = $matches[1][0];
|
$attributeString = $matches[1][0];
|
||||||
|
|
||||||
$Block['element']['attributes'] = $this->parseAttributes($attributeString);
|
$Block['element']['attributes'] = $this->parseAttributeData($attributeString);
|
||||||
|
|
||||||
$Block['element']['text'] = substr($Block['element']['text'], 0, $matches[0][1]);
|
$Block['element']['text'] = substr($Block['element']['text'], 0, $matches[0][1]);
|
||||||
}
|
}
|
||||||
@ -160,78 +219,70 @@ class ParsedownExtra extends Parsedown
|
|||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Definitions
|
# Markup
|
||||||
#
|
|
||||||
|
|
||||||
#
|
protected function blockMarkupComplete($Block)
|
||||||
# Abbreviation
|
|
||||||
|
|
||||||
protected function identifyAbbreviation($Line)
|
|
||||||
{
|
{
|
||||||
if (preg_match('/^\*\[(.+?)\]:[ ]*(.+?)[ ]*$/', $Line['text'], $matches))
|
if ( ! isset($Block['void']))
|
||||||
{
|
{
|
||||||
$Abbreviation = array(
|
$Block['markup'] = $this->processTag($Block['markup']);
|
||||||
'id' => $matches[1],
|
|
||||||
'data' => $matches[2],
|
|
||||||
);
|
|
||||||
|
|
||||||
return $Abbreviation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $Block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Footnote
|
# Setext
|
||||||
|
|
||||||
protected function identifyFootnote($Line)
|
protected function blockSetextHeader($Line, array $Block = null)
|
||||||
{
|
{
|
||||||
if (preg_match('/^\[\^(.+?)\]:[ ]?(.+)$/', $Line['text'], $matches))
|
$Block = parent::blockSetextHeader($Line, $Block);
|
||||||
{
|
|
||||||
$Footnote = array(
|
|
||||||
'id' => $matches[1],
|
|
||||||
'data' => array(
|
|
||||||
'text' => $matches[2],
|
|
||||||
'count' => null,
|
|
||||||
'number' => null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return $Footnote;
|
if (preg_match('/[ ]*{('.$this->regexAttribute.'+)}[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE))
|
||||||
|
{
|
||||||
|
$attributeString = $matches[1][0];
|
||||||
|
|
||||||
|
$Block['element']['attributes'] = $this->parseAttributeData($attributeString);
|
||||||
|
|
||||||
|
$Block['element']['text'] = substr($Block['element']['text'], 0, $matches[0][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $Block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Spans
|
# Inline Elements
|
||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Footnote Marker
|
# Footnote Marker
|
||||||
|
|
||||||
protected function identifyFootnoteMarker($Excerpt)
|
protected function inlineFootnoteMarker($Excerpt)
|
||||||
{
|
{
|
||||||
if (preg_match('/^\[\^(.+?)\]/', $Excerpt['text'], $matches))
|
if (preg_match('/^\[\^(.+?)\]/', $Excerpt['text'], $matches))
|
||||||
{
|
{
|
||||||
$name = $matches[1];
|
$name = $matches[1];
|
||||||
|
|
||||||
if ( ! isset($this->Definitions['Footnote'][$name]))
|
if ( ! isset($this->DefinitionData['Footnote'][$name]))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->Definitions['Footnote'][$name]['count'] ++;
|
$this->DefinitionData['Footnote'][$name]['count'] ++;
|
||||||
|
|
||||||
if ( ! isset($this->Definitions['Footnote'][$name]['number']))
|
if ( ! isset($this->DefinitionData['Footnote'][$name]['number']))
|
||||||
{
|
{
|
||||||
$this->Definitions['Footnote'][$name]['number'] = ++ $this->footnoteCount; # » &
|
$this->DefinitionData['Footnote'][$name]['number'] = ++ $this->footnoteCount; # » &
|
||||||
}
|
}
|
||||||
|
|
||||||
$Element = array(
|
$Element = array(
|
||||||
'name' => 'sup',
|
'name' => 'sup',
|
||||||
'attributes' => array('id' => 'fnref'.$this->Definitions['Footnote'][$name]['count'].':'.$name),
|
'attributes' => array('id' => 'fnref'.$this->DefinitionData['Footnote'][$name]['count'].':'.$name),
|
||||||
'handler' => 'element',
|
'handler' => 'element',
|
||||||
'text' => array(
|
'text' => array(
|
||||||
'name' => 'a',
|
'name' => 'a',
|
||||||
'attributes' => array('href' => '#fn:'.$name, 'class' => 'footnote-ref'),
|
'attributes' => array('href' => '#fn:'.$name, 'class' => 'footnote-ref'),
|
||||||
'text' => $this->Definitions['Footnote'][$name]['number'],
|
'text' => $this->DefinitionData['Footnote'][$name]['number'],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -247,34 +298,37 @@ class ParsedownExtra extends Parsedown
|
|||||||
#
|
#
|
||||||
# Link
|
# Link
|
||||||
|
|
||||||
protected function identifyLink($Excerpt)
|
protected function inlineLink($Excerpt)
|
||||||
{
|
{
|
||||||
$Span = parent::identifyLink($Excerpt);
|
$Link = parent::inlineLink($Excerpt);
|
||||||
|
|
||||||
$remainder = substr($Excerpt['text'], $Span['extent']);
|
$remainder = substr($Excerpt['text'], $Link['extent']);
|
||||||
|
|
||||||
if (preg_match('/^[ ]*'.$this->attributesPattern.'/', $remainder, $matches))
|
if (preg_match('/^[ ]*{('.$this->regexAttribute.'+)}/', $remainder, $matches))
|
||||||
{
|
{
|
||||||
$Span['element']['attributes'] += $this->parseAttributes($matches[1]);
|
$Link['element']['attributes'] += $this->parseAttributeData($matches[1]);
|
||||||
|
|
||||||
$Span['extent'] += strlen($matches[0]);
|
$Link['extent'] += strlen($matches[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $Span;
|
return $Link;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# ~
|
# ~
|
||||||
|
#
|
||||||
|
|
||||||
protected function readPlainText($text)
|
protected function unmarkedText($text)
|
||||||
{
|
{
|
||||||
$text = parent::readPlainText($text);
|
$text = parent::unmarkedText($text);
|
||||||
|
|
||||||
if (isset($this->Definitions['Abbreviation']))
|
if (isset($this->DefinitionData['Abbreviation']))
|
||||||
{
|
{
|
||||||
foreach ($this->Definitions['Abbreviation'] as $abbreviation => $phrase)
|
foreach ($this->DefinitionData['Abbreviation'] as $abbreviation => $meaning)
|
||||||
{
|
{
|
||||||
$text = str_replace($abbreviation, '<abbr title="'.$phrase.'">'.$abbreviation.'</abbr>', $text);
|
$pattern = '/\b'.preg_quote($abbreviation, '/').'\b/';
|
||||||
|
|
||||||
|
$text = preg_replace($pattern, '<abbr title="'.$meaning.'">'.$abbreviation.'</abbr>', $text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,9 +336,34 @@ class ParsedownExtra extends Parsedown
|
|||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# ~
|
# Util Methods
|
||||||
#
|
#
|
||||||
|
|
||||||
|
protected function addDdElement(array $Line, array $Block)
|
||||||
|
{
|
||||||
|
$text = substr($Line['text'], 1);
|
||||||
|
$text = trim($text);
|
||||||
|
|
||||||
|
unset($Block['dd']);
|
||||||
|
|
||||||
|
$Block['dd'] = array(
|
||||||
|
'name' => 'dd',
|
||||||
|
'handler' => 'line',
|
||||||
|
'text' => $text,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($Block['interrupted']))
|
||||||
|
{
|
||||||
|
$Block['dd']['handler'] = 'text';
|
||||||
|
|
||||||
|
unset($Block['interrupted']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$Block['element']['text'] []= & $Block['dd'];
|
||||||
|
|
||||||
|
return $Block;
|
||||||
|
}
|
||||||
|
|
||||||
protected function buildFootnoteElement()
|
protected function buildFootnoteElement()
|
||||||
{
|
{
|
||||||
$Element = array(
|
$Element = array(
|
||||||
@ -303,45 +382,54 @@ class ParsedownExtra extends Parsedown
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
usort($this->Definitions['Footnote'], function($A, $B) {
|
uasort($this->DefinitionData['Footnote'], 'self::sortFootnotes');
|
||||||
return $A['number'] - $B['number'];
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach ($this->Definitions['Footnote'] as $name => $Data)
|
foreach ($this->DefinitionData['Footnote'] as $definitionId => $DefinitionData)
|
||||||
{
|
{
|
||||||
if ( ! isset($Data['number']))
|
if ( ! isset($DefinitionData['number']))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$text = $Data['text'];
|
$text = $DefinitionData['text'];
|
||||||
|
|
||||||
foreach (range(1, $Data['count']) as $number)
|
$text = parent::text($text);
|
||||||
|
|
||||||
|
$numbers = range(1, $DefinitionData['count']);
|
||||||
|
|
||||||
|
$backLinksMarkup = '';
|
||||||
|
|
||||||
|
foreach ($numbers as $number)
|
||||||
{
|
{
|
||||||
$text .= ' <a href="#fnref'.$number.':'.$name.'" rev="footnote" class="footnote-backref">↩</a>';
|
$backLinksMarkup .= ' <a href="#fnref'.$number.':'.$definitionId.'" rev="footnote" class="footnote-backref">↩</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$backLinksMarkup = substr($backLinksMarkup, 1);
|
||||||
|
|
||||||
|
if (substr($text, - 4) === '</p>')
|
||||||
|
{
|
||||||
|
$backLinksMarkup = ' '.$backLinksMarkup;
|
||||||
|
|
||||||
|
$text = substr_replace($text, $backLinksMarkup.'</p>', - 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$text .= "\n".'<p>'.$backLinksMarkup.'</p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$Element['text'][1]['text'] []= array(
|
$Element['text'][1]['text'] []= array(
|
||||||
'name' => 'li',
|
'name' => 'li',
|
||||||
'attributes' => array('id' => 'fn:'.$name),
|
'attributes' => array('id' => 'fn:'.$definitionId),
|
||||||
'handler' => 'elements',
|
'text' => "\n".$text."\n",
|
||||||
'text' => array(
|
|
||||||
array(
|
|
||||||
'name' => 'p',
|
|
||||||
'text' => $text,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $Element;
|
return $Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
# ~
|
||||||
# Private
|
|
||||||
#
|
|
||||||
|
|
||||||
private function parseAttributes($attributeString)
|
protected function parseAttributeData($attributeString)
|
||||||
{
|
{
|
||||||
$Data = array();
|
$Data = array();
|
||||||
|
|
||||||
@ -367,5 +455,72 @@ class ParsedownExtra extends Parsedown
|
|||||||
return $Data;
|
return $Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private $attributesPattern = '{((?:[#.][-\w]+[ ]*)+)}';
|
# ~
|
||||||
|
|
||||||
|
protected function processTag($elementMarkup) # recursive
|
||||||
|
{
|
||||||
|
# http://stackoverflow.com/q/1148928/200145
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
|
||||||
|
$DOMDocument = new DOMDocument;
|
||||||
|
|
||||||
|
# http://stackoverflow.com/q/11309194/200145
|
||||||
|
$elementMarkup = mb_convert_encoding($elementMarkup, 'HTML-ENTITIES', 'UTF-8');
|
||||||
|
|
||||||
|
# http://stackoverflow.com/q/4879946/200145
|
||||||
|
$DOMDocument->loadHTML($elementMarkup);
|
||||||
|
$DOMDocument->removeChild($DOMDocument->doctype);
|
||||||
|
$DOMDocument->replaceChild($DOMDocument->firstChild->firstChild->firstChild, $DOMDocument->firstChild);
|
||||||
|
|
||||||
|
$elementText = '';
|
||||||
|
|
||||||
|
if ($DOMDocument->documentElement->getAttribute('markdown') === '1')
|
||||||
|
{
|
||||||
|
foreach ($DOMDocument->documentElement->childNodes as $Node)
|
||||||
|
{
|
||||||
|
$elementText .= $DOMDocument->saveHTML($Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
$DOMDocument->documentElement->removeAttribute('markdown');
|
||||||
|
|
||||||
|
$elementText = "\n".$this->text($elementText)."\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach ($DOMDocument->documentElement->childNodes as $Node)
|
||||||
|
{
|
||||||
|
$nodeMarkup = $DOMDocument->saveHTML($Node);
|
||||||
|
|
||||||
|
if ($Node instanceof DOMElement and ! in_array($Node->nodeName, $this->textLevelElements))
|
||||||
|
{
|
||||||
|
$elementText .= $this->processTag($nodeMarkup);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$elementText .= $nodeMarkup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# because we don't want for markup to get encoded
|
||||||
|
$DOMDocument->documentElement->nodeValue = 'placeholder\x1A';
|
||||||
|
|
||||||
|
$markup = $DOMDocument->saveHTML($DOMDocument->documentElement);
|
||||||
|
$markup = str_replace('placeholder\x1A', $elementText, $markup);
|
||||||
|
|
||||||
|
return $markup;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ~
|
||||||
|
|
||||||
|
protected function sortFootnotes($A, $B) # callback
|
||||||
|
{
|
||||||
|
return $A['number'] - $B['number'];
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Fields
|
||||||
|
#
|
||||||
|
|
||||||
|
protected $regexAttribute = '(?:[#.][-\w]+[ ]*)';
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user