1
0
mirror of https://github.com/typemill/typemill.git synced 2025-08-09 07:36:34 +02:00

Version 1.2.15: Beautiful Math Refactored

This commit is contained in:
Trendschau
2019-06-04 17:07:11 +02:00
parent 3bcc03e5fb
commit 3fce3a5c61
36 changed files with 727 additions and 253 deletions

View File

@@ -10,14 +10,19 @@ class ParsedownExtension extends \ParsedownExtra
{
parent::__construct();
# mathjax support
$this->InlineTypes['`'][] = 'MathJaxLaTeX';
$this->BlockTypes['`'][] = 'FencedMathJaxLaTeX';
# math support
$this->BlockTypes['\\'][] = 'Math';
$this->BlockTypes['$'][] = 'Math';
$this->InlineTypes['\\'][] = 'Math';
$this->InlineTypes['$'][] = 'Math';
$this->inlineMarkerList .= '\\';
$this->inlineMarkerList .= '$';
# table of content support
array_unshift($this->BlockTypes['['], 'TableOfContents');
}
public function text($text)
{
$Elements = $this->textElements($text);
@@ -72,7 +77,7 @@ class ParsedownExtension extends \ParsedownExtra
return $footnotes;
}
# TableOfContents
protected function blockTableOfContents($line, $block)
@@ -125,8 +130,8 @@ class ParsedownExtension extends \ParsedownExtra
}
}
# build the markup for table of contents
# build the markup for table of contents
public function buildTOC($headlines)
{
$markup = '<ul class="TOC">';
@@ -165,40 +170,23 @@ class ParsedownExtension extends \ParsedownExtra
#
# Footnote Marker
# add absolute url
protected function inlineFootnoteMarker($Excerpt)
{
if (preg_match('/^\[\^(.+?)\]/', $Excerpt['text'], $matches))
$element = parent::inlineFootnoteMarker($Excerpt);
if ( ! isset($element))
{
$name = $matches[1];
if ( ! isset($this->DefinitionData['Footnote'][$name]))
{
return;
}
$this->DefinitionData['Footnote'][$name]['count'] ++;
if ( ! isset($this->DefinitionData['Footnote'][$name]['number']))
{
$this->DefinitionData['Footnote'][$name]['number'] = ++ $this->footnoteCount; # » &
}
$Element = array(
'name' => 'sup',
'attributes' => array('id' => 'fnref'.$this->DefinitionData['Footnote'][$name]['count'].':'.$name),
'element' => array(
'name' => 'a',
'attributes' => array('href' => $this->relurl . '#fn:' . $name, 'class' => 'footnote-ref'),
'text' => $this->DefinitionData['Footnote'][$name]['number'],
),
);
return array(
'extent' => strlen($matches[0]),
'element' => $Element,
);
return null;
}
$href = $element['element']['element']['attributes']['href'];
$element['element']['element']['attributes']['href'] = $this->relurl . $href;
return $element;
}
public $footnoteCount = 0;
@@ -295,129 +283,112 @@ class ParsedownExtension extends \ParsedownExtra
return $Element;
}
# math support. Check https://github.com/aidantwoods/parsedown/blob/mathjaxlatex/ParsedownExtensionMathJaxLaTeX.php
# Inline Math
# check https://github.com/BenjaminHoegh/ParsedownMath
# check https://github.com/cben/mathdown/wiki/math-in-markdown
protected function inlineCode($Excerpt)
protected function inlineMath($Excerpt)
{
$marker = $Excerpt['text'][0];
if (preg_match('/^('.$marker.')[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
if(preg_match('/^(?<!\\\\)(?<!\\\\\()\\\\\((.*?)(?<!\\\\\()\\\\\)(?!\\\\\))/s', $Excerpt['text'], $matches) OR preg_match('/\$(?!\$)([^ ][^\$\n]+)(?<! )\$(?![1-9])/s', $Excerpt['text'], $matches))
{
$text = $matches[2];
$text = preg_replace("/[ ]*\n/", ' ', $text);
return array(
'extent' => strlen($matches[0]),
'element' => array(
'name' => 'code',
'text' => $text,
'text' => '\(' . $matches[1] . '\)',
),
);
);
}
}
protected function inlineMathJaxLaTeX($Excerpt)
}
protected $specialCharacters = array(
'\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '<', '>', '#', '+', '-', '.', '!', '|', '~', '^', '='
);
//
// Inline Escape
// -------------------------------------------------------------------------
protected function inlineEscapeSequence($Excerpt)
{
$marker = $Excerpt['text'][0];
if (preg_match('/^('.$marker.'{2,})[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
{
$text = $matches[2];
$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
$text = preg_replace("/[ ]*\n/", ' ', $text);
if (isset($Excerpt['text'][1])
&& in_array($Excerpt['text'][1], $this->specialCharacters)
&& !preg_match('/(?<!\\\\)((?<!\\\\\()\\\\\((?!\\\\\())(.*?)(?<!\\\\)(?<!\\\\\()((?<!\\\\\))\\\\\)(?!\\\\\)))(?!\\\\\()/s', $Excerpt['text'])
&& !preg_match('/\$(?!\$)([^ ][^\$\n]+)(?<! )\$(?![1-9])/s', $Excerpt['text'])
){
return array(
'extent' => strlen($matches[0]),
'element' => array(
'name' => 'span',
'text' => '\('.$text.'\)',
'rawHtml' => $Excerpt['text'][1],
),
'extent' => 2,
);
}
}
#
# Fenced Code
protected function blockFencedCode($Line)
# Block Math
protected function blockMath($Line)
{
if (preg_match('/^(['.$Line['text'][0].']{3,})[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches))
{
$Element = array(
'name' => 'code',
$Block = array(
'element' => array(
'text' => '',
);
if (isset($matches[2]))
{
if (strtolower($matches[2]) === 'latex')
{
return;
}
$class = 'language-'.$matches[2];
$Element['attributes'] = array(
'class' => $class,
);
}
$Block = array(
'char' => $Line['text'][0],
'openerLength' => mb_strlen($matches[1]),
'element' => array(
'name' => 'pre',
'element' => $Element,
),
);
return $Block;
}
}
#
# Fenced MathJax
protected function blockFencedMathJaxLaTeX($Line)
{
if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches))
),
);
if (preg_match('/^(?<!\\\\)(\\\\\[)(?!.)$/', $Line['text']))
{
if ( ! isset($matches[1]) or strtolower($matches[1]) !== 'latex')
{
return;
}
$Block = array(
'char' => $Line['text'][0],
'element' => array(
'name' => 'span',
'text' => '',
),
);
$Block['end'] = '\]';
return $Block;
}
elseif (preg_match('/^(?<!\\\\)(\$\$)(?!.)$/', $Line['text']))
{
$Block['end'] = '$$';
return $Block;
}
}
protected function blockFencedMathJaxLaTeXContinue($Line, $Block)
// ~
protected function blockMathContinue($Line, $Block)
{
if (isset($Block['complete']))
if (isset($Block['complete']))
{
return;
}
if (isset($Block['interrupted']))
if (isset($Block['interrupted']))
{
$Block['element']['text'] .= "\n";
$Block['element']['text'] .= str_repeat("\n", $Block['interrupted']);
unset($Block['interrupted']);
}
if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
if ($Block['end'] === '\]' && preg_match('/^(?<!\\\\)(\\\\\])$/', $Line['text']))
{
$Block['element']['text'] = substr($Block['element']['text'], 1);
$Block['complete'] = true;
$Block['latex'] = true;
$Block['element']['name'] = 'div';
$Block['element']['text'] = "\\[".$Block['element']['text']."\n\\]";
$Block['element']['attributes'] = array('class' => 'math');
return $Block;
}
elseif ($Block['end'] === '$$' && preg_match('/^(?<!\\\\)(\$\$)$/', $Line['text']))
{
$Block['complete'] = true;
$Block['latex'] = true;
$Block['element']['name'] = 'div';
$Block['element']['text'] = "$$".$Block['element']['text']."\n$$";
$Block['element']['attributes'] = array('class' => 'math');
return $Block;
}
$Block['element']['text'] .= "\n".$Line['body'];;
$Block['element']['text'] .= "\n" . $Line['body'];
// ~
return $Block;
}
protected function blockFencedMathJaxLaTeXComplete($Block)
// ~
protected function blockMathComplete($Block)
{
$text = $Block['element']['text'];
$Block['element']['text'] = "\$\$\n" . $text . "\n\$\$";
return $Block;
}
# advanced attribute data, check parsedown extra plugin: https://github.com/tovic/parsedown-extra-plugin
protected function parseAttributeData($text) {
// Allow compact attributes ...

View File

@@ -0,0 +1,165 @@
<?php
namespace Typemill\Extensions;
class ParsedownMath extends \ParsedownExtra
{
const VERSION = '1.0';
public function __construct()
{
if (version_compare(parent::version, '1.7.1') < 0) {
# die('need version 1.7.1');
# throw new Exception('ParsedownMath requires a later version of Parsedown');
}
// Blocks
$this->BlockTypes['\\'][] = 'Math';
$this->BlockTypes['$'][] = 'Math';
// Inline
$this->InlineTypes['\\'][] = 'Math';
$this->inlineMarkerList .= '\\';
}
// Setters
protected $mathMode = true;
public function enableMath($input = true)
{
$this->mathMode = $input;
if ($input == false) {
return $this;
}
return $this;
}
// -------------------------------------------------------------------------
// ----------------------- Inline --------------------------
// -------------------------------------------------------------------------
//
// Inline Math
// -------------------------------------------------------------------------
protected function inlineMath($Excerpt)
{
if (!$this->mathMode) {
return;
}
// if (preg_match('/^(?<!\\\\)((?<!\\\\\()\\\\\((?!\\\\\())(.*?)(?<!\\\\)(?<!\\\\\()((?<!\\\\\))\\\\\)(?!\\\\\)))(?!\\\\\()/s', $Excerpt['text'], $matches)) {
if (preg_match('/^(?<!\\\\)(?<!\\\\\()\\\\\((.*?)(?<!\\\\\()\\\\\)(?!\\\\\))/s', $Excerpt['text'], $matches)) {
return array(
'extent' => strlen($matches[0]),
'element' => array(
'text' => $matches[0]
),
);
}
}
protected $specialCharacters = array(
'\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '<', '>', '#', '+', '-', '.', '!', '|', '~', '^', '='
);
//
// Inline Escape
// -------------------------------------------------------------------------
protected function inlineEscapeSequence($Excerpt)
{
$Element = array(
'element' => array(
'rawHtml' => $Excerpt['text'][1],
),
'extent' => 2,
);
if ($this->mathMode) {
if (isset($Excerpt['text'][1]) && in_array($Excerpt['text'][1], $this->specialCharacters) && !preg_match('/(?<!\\\\)((?<!\\\\\()\\\\\((?!\\\\\())(.*?)(?<!\\\\)(?<!\\\\\()((?<!\\\\\))\\\\\)(?!\\\\\)))(?!\\\\\()/s', $Excerpt['text'])) {
return $Element;
}
} else {
if (isset($Excerpt['text'][1]) && in_array($Excerpt['text'][1], $this->specialCharacters)) {
return $Element;
}
}
}
// -------------------------------------------------------------------------
// ----------------------- Blocks --------------------------
// -------------------------------------------------------------------------
//
// Block Math
// --------------------------------------------------------------------------
protected function blockMath($Line)
{
$Block = array(
'element' => array(
'text' => '',
),
);
if (preg_match('/^(?<!\\\\)(\\\\\[)(?!.)$/', $Line['text'])) {
$Block['end'] = '\]';
return $Block;
} elseif (preg_match('/^(?<!\\\\)(\$\$)(?!.)$/', $Line['text'])) {
$Block['end'] = '$$';
return $Block;
}
}
// ~
protected function blockMathContinue($Line, $Block)
{
if (isset($Block['complete'])) {
return;
}
if (isset($Block['interrupted'])) {
$Block['element']['text'] .= str_repeat("\n", $Block['interrupted']);
unset($Block['interrupted']);
}
if (preg_match('/^(?<!\\\\)(\\\\\])$/', $Line['text']) && $Block['end'] === '\]') {
$Block['complete'] = true;
$Block['latex'] = true;
$Block['element']['text'] = "\\[".$Block['element']['text']."\\]";
return $Block;
} elseif (preg_match('/^(?<!\\\\)(\$\$)$/', $Line['text']) && $Block['end'] === '$$') {
$Block['complete'] = true;
$Block['latex'] = true;
$Block['element']['text'] = "$$".$Block['element']['text']."$$";
return $Block;
}
$Block['element']['text'] .= "\n" . $Line['body'];
// ~
return $Block;
}
// ~
protected function blockMathComplete($Block)
{
return $Block;
}
}