Changeset 1153658
- Timestamp:
- 05/05/2015 11:13:01 AM (11 years ago)
- Location:
- wp-parsedown/trunk
- Files:
-
- 1 deleted
- 6 edited
-
lib/parsedown-extra/ParsedownExtra.php (modified) (14 diffs)
-
lib/parsedown-extra/README.md (modified) (2 diffs)
-
lib/parsedown/Parsedown.php (modified) (52 diffs)
-
lib/parsedown/README.md (modified) (3 diffs)
-
readme.txt (modified) (2 diffs)
-
wp-common (deleted)
-
wp-parsedown.php (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
wp-parsedown/trunk/lib/parsedown-extra/ParsedownExtra.php
r953966 r1153658 16 16 class ParsedownExtra extends Parsedown 17 17 { 18 # 18 # ~ 19 20 const version = '0.7.0'; 21 19 22 # ~ 20 23 21 24 function __construct() 22 25 { 26 if (parent::version < '1.5.0') 27 { 28 throw new Exception('ParsedownExtra requires a later version of Parsedown'); 29 } 30 23 31 $this->BlockTypes[':'] []= 'DefinitionList'; 24 25 $this->DefinitionTypes['*'] []= 'Abbreviation'; 32 $this->BlockTypes['*'] []= 'Abbreviation'; 26 33 27 34 # identify footnote definitions before reference definitions 28 array_unshift($this-> DefinitionTypes['['], 'Footnote');35 array_unshift($this->BlockTypes['['], 'Footnote'); 29 36 30 37 # identify footnote markers before before links 31 array_unshift($this-> SpanTypes['['], 'FootnoteMarker');38 array_unshift($this->InlineTypes['['], 'FootnoteMarker'); 32 39 } 33 40 … … 45 52 # add footnotes 46 53 47 if (isset($this->Definition s['Footnote']))54 if (isset($this->DefinitionData['Footnote'])) 48 55 { 49 56 $Element = $this->buildFootnoteElement(); … … 60 67 61 68 # 62 # Atx 63 64 protected function identifyAtx($Line) 65 { 66 $Block = parent::identifyAtx($Line); 67 68 if (preg_match('/[ ]*'.$this->attributesPattern.'[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE)) 69 { 70 $attributeString = $matches[1][0]; 71 72 $Block['element']['attributes'] = $this->parseAttributes($attributeString); 73 74 $Block['element']['text'] = substr($Block['element']['text'], 0, $matches[0][1]); 75 } 69 # Abbreviation 70 71 protected function blockAbbreviation($Line) 72 { 73 if (preg_match('/^\*\[(.+?)\]:[ ]*(.+?)[ ]*$/', $Line['text'], $matches)) 74 { 75 $this->DefinitionData['Abbreviation'][$matches[1]] = $matches[2]; 76 77 $Block = array( 78 'hidden' => true, 79 ); 80 81 return $Block; 82 } 83 } 84 85 # 86 # Footnote 87 88 protected function blockFootnote($Line) 89 { 90 if (preg_match('/^\[\^(.+?)\]:[ ]?(.*)$/', $Line['text'], $matches)) 91 { 92 $Block = array( 93 'label' => $matches[1], 94 'text' => $matches[2], 95 'hidden' => true, 96 ); 97 98 return $Block; 99 } 100 } 101 102 protected function blockFootnoteContinue($Line, $Block) 103 { 104 if ($Line['text'][0] === '[' and preg_match('/^\[\^(.+?)\]:/', $Line['text'])) 105 { 106 return; 107 } 108 109 if (isset($Block['interrupted'])) 110 { 111 if ($Line['indent'] >= 4) 112 { 113 $Block['text'] .= "\n\n" . $Line['text']; 114 115 return $Block; 116 } 117 } 118 else 119 { 120 $Block['text'] .= "\n" . $Line['text']; 121 122 return $Block; 123 } 124 } 125 126 protected function blockFootnoteComplete($Block) 127 { 128 $this->DefinitionData['Footnote'][$Block['label']] = array( 129 'text' => $Block['text'], 130 'count' => null, 131 'number' => null, 132 ); 76 133 77 134 return $Block; … … 81 138 # Definition List 82 139 83 protected function identifyDefinitionList($Line, $Block)84 { 85 if ( isset($Block['type']))140 protected function blockDefinitionList($Line, $Block) 141 { 142 if ( ! isset($Block) or isset($Block['type'])) 86 143 { 87 144 return; … … 105 162 } 106 163 107 $Element['text'] []= array(108 'name' => 'dd',109 'handler' => 'line',110 'text' => ltrim($Line['text'], ' :'),111 );112 113 164 $Block['element'] = $Element; 114 165 166 $Block = $this->addDdElement($Line, $Block); 167 115 168 return $Block; 116 169 } 117 170 118 protected function addToDefinitionList($Line, array $Block)171 protected function blockDefinitionListContinue($Line, array $Block) 119 172 { 120 173 if ($Line['text'][0] === ':') 121 174 { 122 $Block['element']['text'] []= array( 123 'name' => 'dd', 124 'handler' => 'line', 125 'text' => ltrim($Line['text'], ' :'), 126 ); 175 $Block = $this->addDdElement($Line, $Block); 127 176 128 177 return $Block; 129 178 } 130 131 if ( ! isset($Block['interrupted'])) 132 { 133 $Element = array_pop($Block['element']['text']); 134 135 $Element['text'] .= "\n" . chop($Line['text']); 136 137 $Block['element']['text'] []= $Element; 179 else 180 { 181 if (isset($Block['interrupted']) and $Line['indent'] === 0) 182 { 183 return; 184 } 185 186 if (isset($Block['interrupted'])) 187 { 188 $Block['dd']['handler'] = 'text'; 189 $Block['dd']['text'] .= "\n\n"; 190 191 unset($Block['interrupted']); 192 } 193 194 $text = substr($Line['body'], min($Line['indent'], 4)); 195 196 $Block['dd']['text'] .= "\n" . $text; 138 197 139 198 return $Block; … … 142 201 143 202 # 203 # Header 204 205 protected function blockHeader($Line) 206 { 207 $Block = parent::blockHeader($Line); 208 209 if (preg_match('/[ #]*{('.$this->regexAttribute.'+)}[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE)) 210 { 211 $attributeString = $matches[1][0]; 212 213 $Block['element']['attributes'] = $this->parseAttributeData($attributeString); 214 215 $Block['element']['text'] = substr($Block['element']['text'], 0, $matches[0][1]); 216 } 217 218 return $Block; 219 } 220 221 # 222 # Markup 223 224 protected function blockMarkupComplete($Block) 225 { 226 if ( ! isset($Block['void'])) 227 { 228 $Block['markup'] = $this->processTag($Block['markup']); 229 } 230 231 return $Block; 232 } 233 234 # 144 235 # Setext 145 236 146 protected function identifySetext($Line, array $Block = null)147 { 148 $Block = parent:: identifySetext($Line, $Block);149 150 if (preg_match('/[ ]* '.$this->attributesPattern.'[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE))237 protected function blockSetextHeader($Line, array $Block = null) 238 { 239 $Block = parent::blockSetextHeader($Line, $Block); 240 241 if (preg_match('/[ ]*{('.$this->regexAttribute.'+)}[ ]*$/', $Block['element']['text'], $matches, PREG_OFFSET_CAPTURE)) 151 242 { 152 243 $attributeString = $matches[1][0]; 153 244 154 $Block['element']['attributes'] = $this->parseAttribute s($attributeString);245 $Block['element']['attributes'] = $this->parseAttributeData($attributeString); 155 246 156 247 $Block['element']['text'] = substr($Block['element']['text'], 0, $matches[0][1]); … … 161 252 162 253 # 163 # Definitions 164 # 165 166 # 167 # Abbreviation 168 169 protected function identifyAbbreviation($Line) 170 { 171 if (preg_match('/^\*\[(.+?)\]:[ ]*(.+?)[ ]*$/', $Line['text'], $matches)) 172 { 173 $Abbreviation = array( 174 'id' => $matches[1], 175 'data' => $matches[2], 176 ); 177 178 return $Abbreviation; 179 } 180 } 181 182 # 183 # Footnote 184 185 protected function identifyFootnote($Line) 186 { 187 if (preg_match('/^\[\^(.+?)\]:[ ]?(.+)$/', $Line['text'], $matches)) 188 { 189 $Footnote = array( 190 'id' => $matches[1], 191 'data' => array( 192 'text' => $matches[2], 193 'count' => null, 194 'number' => null, 195 ), 196 ); 197 198 return $Footnote; 199 } 200 } 201 202 # 203 # Spans 254 # Inline Elements 204 255 # 205 256 … … 207 258 # Footnote Marker 208 259 209 protected function i dentifyFootnoteMarker($Excerpt)260 protected function inlineFootnoteMarker($Excerpt) 210 261 { 211 262 if (preg_match('/^\[\^(.+?)\]/', $Excerpt['text'], $matches)) … … 213 264 $name = $matches[1]; 214 265 215 if ( ! isset($this->Definition s['Footnote'][$name]))266 if ( ! isset($this->DefinitionData['Footnote'][$name])) 216 267 { 217 268 return; 218 269 } 219 270 220 $this->Definition s['Footnote'][$name]['count'] ++;221 222 if ( ! isset($this->Definition s['Footnote'][$name]['number']))223 { 224 $this->Definition s['Footnote'][$name]['number'] = ++ $this->footnoteCount; # » &271 $this->DefinitionData['Footnote'][$name]['count'] ++; 272 273 if ( ! isset($this->DefinitionData['Footnote'][$name]['number'])) 274 { 275 $this->DefinitionData['Footnote'][$name]['number'] = ++ $this->footnoteCount; # » & 225 276 } 226 277 227 278 $Element = array( 228 279 'name' => 'sup', 229 'attributes' => array('id' => 'fnref'.$this->Definition s['Footnote'][$name]['count'].':'.$name),280 'attributes' => array('id' => 'fnref'.$this->DefinitionData['Footnote'][$name]['count'].':'.$name), 230 281 'handler' => 'element', 231 282 'text' => array( 232 283 'name' => 'a', 233 284 'attributes' => array('href' => '#fn:'.$name, 'class' => 'footnote-ref'), 234 'text' => $this->Definition s['Footnote'][$name]['number'],285 'text' => $this->DefinitionData['Footnote'][$name]['number'], 235 286 ), 236 287 ); … … 248 299 # Link 249 300 250 protected function identifyLink($Excerpt) 251 { 252 $Span = parent::identifyLink($Excerpt); 253 254 $remainder = substr($Excerpt['text'], $Span['extent']); 255 256 if (preg_match('/^[ ]*'.$this->attributesPattern.'/', $remainder, $matches)) 257 { 258 $Span['element']['attributes'] += $this->parseAttributes($matches[1]); 259 260 $Span['extent'] += strlen($matches[0]); 261 } 262 263 return $Span; 264 } 265 266 # 267 # ~ 268 269 protected function readPlainText($text) 270 { 271 $text = parent::readPlainText($text); 272 273 if (isset($this->Definitions['Abbreviation'])) 274 { 275 foreach ($this->Definitions['Abbreviation'] as $abbreviation => $phrase) 276 { 277 $text = str_replace($abbreviation, '<abbr title="'.$phrase.'">'.$abbreviation.'</abbr>', $text); 301 protected function inlineLink($Excerpt) 302 { 303 $Link = parent::inlineLink($Excerpt); 304 305 $remainder = substr($Excerpt['text'], $Link['extent']); 306 307 if (preg_match('/^[ ]*{('.$this->regexAttribute.'+)}/', $remainder, $matches)) 308 { 309 $Link['element']['attributes'] += $this->parseAttributeData($matches[1]); 310 311 $Link['extent'] += strlen($matches[0]); 312 } 313 314 return $Link; 315 } 316 317 # 318 # ~ 319 # 320 321 protected function unmarkedText($text) 322 { 323 $text = parent::unmarkedText($text); 324 325 if (isset($this->DefinitionData['Abbreviation'])) 326 { 327 foreach ($this->DefinitionData['Abbreviation'] as $abbreviation => $meaning) 328 { 329 $pattern = '/\b'.preg_quote($abbreviation, '/').'\b/'; 330 331 $text = preg_replace($pattern, '<abbr title="'.$meaning.'">'.$abbreviation.'</abbr>', $text); 278 332 } 279 333 } … … 283 337 284 338 # 285 # ~ 286 # 339 # Util Methods 340 # 341 342 protected function addDdElement(array $Line, array $Block) 343 { 344 $text = substr($Line['text'], 1); 345 $text = trim($text); 346 347 unset($Block['dd']); 348 349 $Block['dd'] = array( 350 'name' => 'dd', 351 'handler' => 'line', 352 'text' => $text, 353 ); 354 355 if (isset($Block['interrupted'])) 356 { 357 $Block['dd']['handler'] = 'text'; 358 359 unset($Block['interrupted']); 360 } 361 362 $Block['element']['text'] []= & $Block['dd']; 363 364 return $Block; 365 } 287 366 288 367 protected function buildFootnoteElement() … … 304 383 ); 305 384 306 usort($this->Definitions['Footnote'], function($A, $B) { 307 return $A['number'] - $B['number']; 308 }); 309 310 foreach ($this->Definitions['Footnote'] as $name => $Data) 311 { 312 if ( ! isset($Data['number'])) 385 uasort($this->DefinitionData['Footnote'], 'self::sortFootnotes'); 386 387 foreach ($this->DefinitionData['Footnote'] as $definitionId => $DefinitionData) 388 { 389 if ( ! isset($DefinitionData['number'])) 313 390 { 314 391 continue; 315 392 } 316 393 317 $text = $Data['text']; 318 319 foreach (range(1, $Data['count']) as $number) 320 { 321 $text .= ' <a href="#fnref'.$number.':'.$name.'" rev="footnote" class="footnote-backref">↩</a>'; 394 $text = $DefinitionData['text']; 395 396 $text = parent::text($text); 397 398 $numbers = range(1, $DefinitionData['count']); 399 400 $backLinksMarkup = ''; 401 402 foreach ($numbers as $number) 403 { 404 $backLinksMarkup .= ' <a href="#fnref'.$number.':'.$definitionId.'" rev="footnote" class="footnote-backref">↩</a>'; 405 } 406 407 $backLinksMarkup = substr($backLinksMarkup, 1); 408 409 if (substr($text, - 4) === '</p>') 410 { 411 $backLinksMarkup = ' '.$backLinksMarkup; 412 413 $text = substr_replace($text, $backLinksMarkup.'</p>', - 4); 414 } 415 else 416 { 417 $text .= "\n".'<p>'.$backLinksMarkup.'</p>'; 322 418 } 323 419 324 420 $Element['text'][1]['text'] []= array( 325 421 'name' => 'li', 326 'attributes' => array('id' => 'fn:'.$name), 327 'handler' => 'elements', 328 'text' => array( 329 array( 330 'name' => 'p', 331 'text' => $text, 332 ), 333 ), 422 'attributes' => array('id' => 'fn:'.$definitionId), 423 'text' => "\n".$text."\n", 334 424 ); 335 425 } … … 338 428 } 339 429 340 # 341 # Private 342 # 343 344 private function parseAttributes($attributeString) 430 # ~ 431 432 protected function parseAttributeData($attributeString) 345 433 { 346 434 $Data = array(); … … 368 456 } 369 457 370 private $attributesPattern = '{((?:[#.][-\w]+[ ]*)+)}'; 458 # ~ 459 460 protected function processTag($elementMarkup) # recursive 461 { 462 # http://stackoverflow.com/q/1148928/200145 463 libxml_use_internal_errors(true); 464 465 $DOMDocument = new DOMDocument; 466 467 # http://stackoverflow.com/q/11309194/200145 468 $elementMarkup = mb_convert_encoding($elementMarkup, 'HTML-ENTITIES', 'UTF-8'); 469 470 # http://stackoverflow.com/q/4879946/200145 471 $DOMDocument->loadHTML($elementMarkup); 472 $DOMDocument->removeChild($DOMDocument->doctype); 473 $DOMDocument->replaceChild($DOMDocument->firstChild->firstChild->firstChild, $DOMDocument->firstChild); 474 475 $elementText = ''; 476 477 if ($DOMDocument->documentElement->getAttribute('markdown') === '1') 478 { 479 foreach ($DOMDocument->documentElement->childNodes as $Node) 480 { 481 $elementText .= $DOMDocument->saveHTML($Node); 482 } 483 484 $DOMDocument->documentElement->removeAttribute('markdown'); 485 486 $elementText = "\n".$this->text($elementText)."\n"; 487 } 488 else 489 { 490 foreach ($DOMDocument->documentElement->childNodes as $Node) 491 { 492 $nodeMarkup = $DOMDocument->saveHTML($Node); 493 494 if ($Node instanceof DOMElement and ! in_array($Node->nodeName, $this->textLevelElements)) 495 { 496 $elementText .= $this->processTag($nodeMarkup); 497 } 498 else 499 { 500 $elementText .= $nodeMarkup; 501 } 502 } 503 } 504 505 # because we don't want for markup to get encoded 506 $DOMDocument->documentElement->nodeValue = 'placeholder'; 507 508 $markup = $DOMDocument->saveHTML($DOMDocument->documentElement); 509 $markup = str_replace('placeholder', $elementText, $markup); 510 511 return $markup; 512 } 513 514 # ~ 515 516 protected function sortFootnotes($A, $B) # callback 517 { 518 return $A['number'] - $B['number']; 519 } 520 521 # 522 # Fields 523 # 524 525 protected $regexAttribute = '(?:[#.][-\w]+[ ]*)'; 371 526 } -
wp-parsedown/trunk/lib/parsedown-extra/README.md
r953966 r1153658 1 1 ## Parsedown Extra 2 2 3 An extension of [Parsedown](http://parsedown.org) that adds support for [Markdown Extra](http://en.wikipedia.org/wiki/Markdown_Extra). 3 [](https://travis-ci.org/erusev/parsedown-extra) 4 4 5 [[ demo ]](http://parsedown.org/demo?extra=1) 5 An extension of [Parsedown](http://parsedown.org) that adds support for [Markdown Extra](https://michelf.ca/projects/php-markdown/extra/). 6 7 [See Demo](http://parsedown.org/extra/) 6 8 7 9 ### Installation … … 12 14 13 15 ``` php 14 $ Instance= new ParsedownExtra();16 $Extra = new ParsedownExtra(); 15 17 16 echo $ Instance->text('Hello _Parsedown Extra_!'); # prints: <p>Hello <em>Parsedown Extra</em>!</p>18 echo $Extra->text('# Header {.sth}'); # prints: <h1 class="sth">Header</h1> 17 19 ``` 20 21 ### Questions 22 23 **Who uses Parsedown Extra?** 24 25 [October CMS](http://octobercms.com/), [Bolt CMS](http://bolt.cm/), [Kirby CMS](http://getkirby.com/), [Grav CMS](http://getgrav.org/), [Statamic CMS](http://www.statamic.com/) and [more](https://www.versioneye.com/php/erusev:parsedown-extra/references). 26 27 **How can I help?** 28 29 Use it, star it, share it and in case you feel generous, [donate some money](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2). -
wp-parsedown/trunk/lib/parsedown/Parsedown.php
r953966 r1153658 16 16 class Parsedown 17 17 { 18 #19 # Philosophy20 21 # Parsedown recognises that the Markdown syntax is optimised for humans so22 # it tries to read like one. It goes through text line by line. It looks at23 # how lines start to identify blocks. It looks for special characters to24 # identify inline elements.25 26 #27 18 # ~ 28 19 20 const version = '1.5.3'; 21 22 # ~ 23 29 24 function text($text) 30 25 { 31 26 # make sure no definitions are set 32 $this->Definition s= array();27 $this->DefinitionData = array(); 33 28 34 29 # standardize line breaks 35 $text = str_replace("\r\n", "\n", $text); 36 $text = str_replace("\r", "\n", $text); 37 38 # replace tabs with spaces 39 $text = str_replace("\t", ' ', $text); 30 $text = str_replace(array("\r\n", "\r"), "\n", $text); 40 31 41 32 # remove surrounding line breaks … … 58 49 # 59 50 60 private $breaksEnabled;61 62 51 function setBreaksEnabled($breaksEnabled) 63 52 { … … 67 56 } 68 57 58 protected $breaksEnabled; 59 60 function setMarkupEscaped($markupEscaped) 61 { 62 $this->markupEscaped = $markupEscaped; 63 64 return $this; 65 } 66 67 protected $markupEscaped; 68 69 function setUrlsLinked($urlsLinked) 70 { 71 $this->urlsLinked = $urlsLinked; 72 73 return $this; 74 } 75 76 protected $urlsLinked = true; 77 69 78 # 70 79 # Lines … … 72 81 73 82 protected $BlockTypes = array( 74 '#' => array(' Atx'),83 '#' => array('Header'), 75 84 '*' => array('Rule', 'List'), 76 85 '+' => array('List'), 77 '-' => array('Setext ', 'Table', 'Rule', 'List'),86 '-' => array('SetextHeader', 'Table', 'Rule', 'List'), 78 87 '0' => array('List'), 79 88 '1' => array('List'), … … 88 97 ':' => array('Table'), 89 98 '<' => array('Comment', 'Markup'), 90 '=' => array('Setext '),99 '=' => array('SetextHeader'), 91 100 '>' => array('Quote'), 101 '[' => array('Reference'), 92 102 '_' => array('Rule'), 93 103 '`' => array('FencedCode'), … … 105 115 106 116 protected $unmarkedBlockTypes = array( 107 'Code Block',117 'Code', 108 118 ); 109 119 … … 128 138 } 129 139 140 if (strpos($line, "\t") !== false) 141 { 142 $parts = explode("\t", $line); 143 144 $line = $parts[0]; 145 146 unset($parts[0]); 147 148 foreach ($parts as $part) 149 { 150 $shortage = 4 - mb_strlen($line, 'utf-8') % 4; 151 152 $line .= str_repeat(' ', $shortage); 153 $line .= $part; 154 } 155 } 156 130 157 $indent = 0; 131 158 … … 145 172 if (isset($CurrentBlock['incomplete'])) 146 173 { 147 $Block = $this->{' addTo'.$CurrentBlock['type']}($Line, $CurrentBlock);174 $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock); 148 175 149 176 if (isset($Block)) … … 155 182 else 156 183 { 157 if (method_exists($this, ' complete'.$CurrentBlock['type']))184 if (method_exists($this, 'block'.$CurrentBlock['type'].'Complete')) 158 185 { 159 $CurrentBlock = $this->{' complete'.$CurrentBlock['type']}($CurrentBlock);186 $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock); 160 187 } 161 188 … … 167 194 168 195 $marker = $text[0]; 169 170 if (isset($this->DefinitionTypes[$marker]))171 {172 foreach ($this->DefinitionTypes[$marker] as $definitionType)173 {174 $Definition = $this->{'identify'.$definitionType}($Line, $CurrentBlock);175 176 if (isset($Definition))177 {178 $this->Definitions[$definitionType][$Definition['id']] = $Definition['data'];179 180 continue 2;181 }182 }183 }184 196 185 197 # ~ … … 200 212 foreach ($blockTypes as $blockType) 201 213 { 202 $Block = $this->{' identify'.$blockType}($Line, $CurrentBlock);214 $Block = $this->{'block'.$blockType}($Line, $CurrentBlock); 203 215 204 216 if (isset($Block)) … … 208 220 if ( ! isset($Block['identified'])) 209 221 { 210 $ Elements []= $CurrentBlock['element'];222 $Blocks []= $CurrentBlock; 211 223 212 224 $Block['identified'] = true; 213 225 } 214 226 215 if (method_exists($this, ' addTo'.$blockType))227 if (method_exists($this, 'block'.$blockType.'Continue')) 216 228 { 217 229 $Block['incomplete'] = true; … … 232 244 else 233 245 { 234 $ Elements []= $CurrentBlock['element'];235 236 $CurrentBlock = $this-> buildParagraph($Line);246 $Blocks []= $CurrentBlock; 247 248 $CurrentBlock = $this->paragraph($Line); 237 249 238 250 $CurrentBlock['identified'] = true; … … 242 254 # ~ 243 255 244 if (isset($CurrentBlock['incomplete']) and method_exists($this, ' complete'.$CurrentBlock['type']))245 { 246 $CurrentBlock = $this->{' complete'.$CurrentBlock['type']}($CurrentBlock);256 if (isset($CurrentBlock['incomplete']) and method_exists($this, 'block'.$CurrentBlock['type'].'Complete')) 257 { 258 $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock); 247 259 } 248 260 249 261 # ~ 250 262 251 $ Elements []= $CurrentBlock['element'];252 253 unset($ Elements[0]);263 $Blocks []= $CurrentBlock; 264 265 unset($Blocks[0]); 254 266 255 267 # ~ 256 268 257 $markup = $this->elements($Elements); 269 $markup = ''; 270 271 foreach ($Blocks as $Block) 272 { 273 if (isset($Block['hidden'])) 274 { 275 continue; 276 } 277 278 $markup .= "\n"; 279 $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']); 280 } 281 282 $markup .= "\n"; 258 283 259 284 # ~ … … 263 288 264 289 # 265 # Atx266 267 protected function identifyAtx($Line)268 {269 if (isset($Line['text'][1]))270 {271 $level = 1;272 273 while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')274 {275 $level ++;276 }277 278 $text = trim($Line['text'], '# ');279 280 $Block = array(281 'element' => array(282 'name' => 'h'.$level,283 'text' => $text,284 'handler' => 'line',285 ),286 );287 288 return $Block;289 }290 }291 292 #293 290 # Code 294 291 295 protected function identifyCodeBlock($Line) 296 { 292 protected function blockCode($Line, $Block = null) 293 { 294 if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted'])) 295 { 296 return; 297 } 298 297 299 if ($Line['indent'] >= 4) 298 300 { … … 314 316 } 315 317 316 protected function addToCodeBlock($Line, $Block)318 protected function blockCodeContinue($Line, $Block) 317 319 { 318 320 if ($Line['indent'] >= 4) … … 335 337 } 336 338 337 protected function completeCodeBlock($Block)339 protected function blockCodeComplete($Block) 338 340 { 339 341 $text = $Block['element']['text']['text']; … … 349 351 # Comment 350 352 351 protected function identifyComment($Line) 352 { 353 protected function blockComment($Line) 354 { 355 if ($this->markupEscaped) 356 { 357 return; 358 } 359 353 360 if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!') 354 361 { 355 362 $Block = array( 356 ' element' => $Line['body'],363 'markup' => $Line['body'], 357 364 ); 358 365 … … 366 373 } 367 374 368 protected function addToComment($Line, array $Block)375 protected function blockCommentContinue($Line, array $Block) 369 376 { 370 377 if (isset($Block['closed'])) … … 373 380 } 374 381 375 $Block[' element'] .= "\n" . $Line['body'];382 $Block['markup'] .= "\n" . $Line['body']; 376 383 377 384 if (preg_match('/-->$/', $Line['text'])) … … 386 393 # Fenced Code 387 394 388 protected function identifyFencedCode($Line)395 protected function blockFencedCode($Line) 389 396 { 390 397 if (preg_match('/^(['.$Line['text'][0].']{3,})[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches)) … … 417 424 } 418 425 419 protected function addToFencedCode($Line, $Block)426 protected function blockFencedCodeContinue($Line, $Block) 420 427 { 421 428 if (isset($Block['complete'])) … … 445 452 } 446 453 447 protected function completeFencedCode($Block)454 protected function blockFencedCodeComplete($Block) 448 455 { 449 456 $text = $Block['element']['text']['text']; … … 457 464 458 465 # 466 # Header 467 468 protected function blockHeader($Line) 469 { 470 if (isset($Line['text'][1])) 471 { 472 $level = 1; 473 474 while (isset($Line['text'][$level]) and $Line['text'][$level] === '#') 475 { 476 $level ++; 477 } 478 479 if ($level > 6) 480 { 481 return; 482 } 483 484 $text = trim($Line['text'], '# '); 485 486 $Block = array( 487 'element' => array( 488 'name' => 'h' . min(6, $level), 489 'text' => $text, 490 'handler' => 'line', 491 ), 492 ); 493 494 return $Block; 495 } 496 } 497 498 # 459 499 # List 460 500 461 protected function identifyList($Line)501 protected function blockList($Line) 462 502 { 463 503 list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]'); … … 488 528 } 489 529 490 protected function addToList($Line, array $Block)491 { 492 if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].' [ ]+(.*)/', $Line['text'], $matches))530 protected function blockListContinue($Line, array $Block) 531 { 532 if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches)) 493 533 { 494 534 if (isset($Block['interrupted'])) … … 500 540 501 541 unset($Block['li']); 542 543 $text = isset($matches[1]) ? $matches[1] : ''; 502 544 503 545 $Block['li'] = array( … … 505 547 'handler' => 'li', 506 548 'text' => array( 507 $ matches[1],549 $text, 508 550 ), 509 551 ); … … 514 556 } 515 557 558 if ($Line['text'][0] === '[' and $this->blockReference($Line)) 559 { 560 return $Block; 561 } 562 516 563 if ( ! isset($Block['interrupted'])) 517 564 { … … 540 587 # Quote 541 588 542 protected function identifyQuote($Line)589 protected function blockQuote($Line) 543 590 { 544 591 if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) … … 556 603 } 557 604 558 protected function addToQuote($Line, array $Block)605 protected function blockQuoteContinue($Line, array $Block) 559 606 { 560 607 if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) … … 583 630 # Rule 584 631 585 protected function identifyRule($Line)586 { 587 if (preg_match('/^(['.$Line['text'][0].'])([ ] {0,2}\1){2,}[ ]*$/', $Line['text']))632 protected function blockRule($Line) 633 { 634 if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text'])) 588 635 { 589 636 $Block = array( … … 600 647 # Setext 601 648 602 protected function identifySetext($Line, array $Block = null)649 protected function blockSetextHeader($Line, array $Block = null) 603 650 { 604 651 if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) … … 618 665 # Markup 619 666 620 protected function identifyMarkup($Line) 621 { 622 if (preg_match('/^<(\w[\w\d]*)(?:[ ][^>\/]*)?(\/?)[ ]*>/', $Line['text'], $matches)) 667 protected function blockMarkup($Line) 668 { 669 if ($this->markupEscaped) 670 { 671 return; 672 } 673 674 if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches)) 623 675 { 624 676 if (in_array($matches[1], $this->textLevelElements)) … … 628 680 629 681 $Block = array( 630 'element' => $Line['body'], 631 ); 632 633 if ($matches[2] or $matches[1] === 'hr' or preg_match('/<\/'.$matches[1].'>[ ]*$/', $Line['text'])) 682 'name' => $matches[1], 683 'depth' => 0, 684 'markup' => $Line['text'], 685 ); 686 687 $length = strlen($matches[0]); 688 689 $remainder = substr($Line['text'], $length); 690 691 if (trim($remainder) === '') 692 { 693 if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) 694 { 695 $Block['closed'] = true; 696 697 $Block['void'] = true; 698 } 699 } 700 else 701 { 702 if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) 703 { 704 return; 705 } 706 707 if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder)) 708 { 709 $Block['closed'] = true; 710 } 711 } 712 713 return $Block; 714 } 715 } 716 717 protected function blockMarkupContinue($Line, array $Block) 718 { 719 if (isset($Block['closed'])) 720 { 721 return; 722 } 723 724 if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open 725 { 726 $Block['depth'] ++; 727 } 728 729 if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close 730 { 731 if ($Block['depth'] > 0) 732 { 733 $Block['depth'] --; 734 } 735 else 634 736 { 635 737 $Block['closed'] = true; 636 738 } 637 else 638 { 639 $Block['depth'] = 0; 640 $Block['name'] = $matches[1]; 641 } 642 643 return $Block; 644 } 645 } 646 647 protected function addToMarkup($Line, array $Block) 648 { 649 if (isset($Block['closed'])) 650 { 651 return; 652 } 653 654 if (preg_match('/<'.$Block['name'].'([ ][^\/]+)?>/', $Line['text'])) # opening tag 655 { 656 $Block['depth'] ++; 657 } 658 659 if (stripos($Line['text'], '</'.$Block['name'].'>') !== false) # closing tag 660 { 661 if ($Block['depth'] > 0) 662 { 663 $Block['depth'] --; 664 } 665 else 666 { 667 $Block['closed'] = true; 668 } 669 } 670 671 $Block['element'] .= "\n".$Line['body']; 739 } 740 741 if (isset($Block['interrupted'])) 742 { 743 $Block['markup'] .= "\n"; 744 745 unset($Block['interrupted']); 746 } 747 748 $Block['markup'] .= "\n".$Line['body']; 672 749 673 750 return $Block; … … 675 752 676 753 # 754 # Reference 755 756 protected function blockReference($Line) 757 { 758 if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) 759 { 760 $id = strtolower($matches[1]); 761 762 $Data = array( 763 'url' => $matches[2], 764 'title' => null, 765 ); 766 767 if (isset($matches[3])) 768 { 769 $Data['title'] = $matches[3]; 770 } 771 772 $this->DefinitionData['Reference'][$id] = $Data; 773 774 $Block = array( 775 'hidden' => true, 776 ); 777 778 return $Block; 779 } 780 } 781 782 # 677 783 # Table 678 784 679 protected function identifyTable($Line, array $Block = null)785 protected function blockTable($Line, array $Block = null) 680 786 { 681 787 if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) … … 711 817 } 712 818 713 if (substr($dividerCell, - 1) === ':')819 if (substr($dividerCell, - 1) === ':') 714 820 { 715 821 $alignment = $alignment === 'left' ? 'center' : 'right'; … … 745 851 746 852 $HeaderElement['attributes'] = array( 747 ' align' => $alignment,853 'style' => 'text-align: '.$alignment.';', 748 854 ); 749 855 } … … 784 890 } 785 891 786 protected function addToTable($Line, array $Block) 787 { 892 protected function blockTableContinue($Line, array $Block) 893 { 894 if (isset($Block['interrupted'])) 895 { 896 return; 897 } 898 788 899 if ($Line['text'][0] === '|' or strpos($Line['text'], '|')) 789 900 { … … 795 906 $row = trim($row, '|'); 796 907 797 $cells = explode('|', $row);798 799 foreach ($ cellsas $index => $cell)908 preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches); 909 910 foreach ($matches[0] as $index => $cell) 800 911 { 801 912 $cell = trim($cell); … … 810 921 { 811 922 $Element['attributes'] = array( 812 ' align' => $Block['alignments'][$index],923 'style' => 'text-align: '.$Block['alignments'][$index].';', 813 924 ); 814 925 } … … 830 941 831 942 # 832 # Definitions833 #834 835 protected function identifyReference($Line)836 {837 if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))838 {839 $Definition = array(840 'id' => strtolower($matches[1]),841 'data' => array(842 'url' => $matches[2],843 ),844 );845 846 if (isset($matches[3]))847 {848 $Definition['data']['title'] = $matches[3];849 }850 851 return $Definition;852 }853 }854 855 #856 943 # ~ 857 944 # 858 945 859 protected function buildParagraph($Line)946 protected function paragraph($Line) 860 947 { 861 948 $Block = array( … … 871 958 872 959 # 873 # ~ 874 # 875 876 protected function element(array $Element) 877 { 878 $markup = '<'.$Element['name']; 879 880 if (isset($Element['attributes'])) 881 { 882 foreach ($Element['attributes'] as $name => $value) 883 { 884 $markup .= ' '.$name.'="'.$value.'"'; 885 } 886 } 887 888 if (isset($Element['text'])) 889 { 890 $markup .= '>'; 891 892 if (isset($Element['handler'])) 893 { 894 $markup .= $this->$Element['handler']($Element['text']); 895 } 896 else 897 { 898 $markup .= $Element['text']; 899 } 900 901 $markup .= '</'.$Element['name'].'>'; 902 } 903 else 904 { 905 $markup .= ' />'; 906 } 907 908 return $markup; 909 } 910 911 protected function elements(array $Elements) 912 { 913 $markup = ''; 914 915 foreach ($Elements as $Element) 916 { 917 if ($Element === null) 918 { 919 continue; 920 } 921 922 $markup .= "\n"; 923 924 if (is_string($Element)) # because of Markup 925 { 926 $markup .= $Element; 927 928 continue; 929 } 930 931 $markup .= $this->element($Element); 932 } 933 934 $markup .= "\n"; 935 936 return $markup; 937 } 938 939 # 940 # Spans 941 # 942 943 protected $SpanTypes = array( 944 '!' => array('Link'), # ? 945 '&' => array('Ampersand'), 960 # Inline Elements 961 # 962 963 protected $InlineTypes = array( 964 '"' => array('SpecialCharacter'), 965 '!' => array('Image'), 966 '&' => array('SpecialCharacter'), 946 967 '*' => array('Emphasis'), 947 '/' => array('Url'), 948 '<' => array('UrlTag', 'EmailTag', 'Tag', 'LessThan'), 968 ':' => array('Url'), 969 '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'), 970 '>' => array('SpecialCharacter'), 949 971 '[' => array('Link'), 950 972 '_' => array('Emphasis'), 951 '`' => array(' InlineCode'),973 '`' => array('Code'), 952 974 '~' => array('Strikethrough'), 953 975 '\\' => array('EscapeSequence'), … … 956 978 # ~ 957 979 958 protected $ spanMarkerList = '*_!&[</`~\\';980 protected $inlineMarkerList = '!"*_&[:<>`~\\'; 959 981 960 982 # … … 966 988 $markup = ''; 967 989 968 $ remainder= $text;990 $unexaminedText = $text; 969 991 970 992 $markerPosition = 0; 971 993 972 while ($excerpt = strpbrk($ remainder, $this->spanMarkerList))994 while ($excerpt = strpbrk($unexaminedText, $this->inlineMarkerList)) 973 995 { 974 996 $marker = $excerpt[0]; 975 997 976 $markerPosition += strpos($ remainder, $marker);998 $markerPosition += strpos($unexaminedText, $marker); 977 999 978 1000 $Excerpt = array('text' => $excerpt, 'context' => $text); 979 1001 980 foreach ($this->SpanTypes[$marker] as $spanType) 981 { 982 $handler = 'identify'.$spanType; 983 984 $Span = $this->$handler($Excerpt); 985 986 if ( ! isset($Span)) 1002 foreach ($this->InlineTypes[$marker] as $inlineType) 1003 { 1004 $Inline = $this->{'inline'.$inlineType}($Excerpt); 1005 1006 if ( ! isset($Inline)) 987 1007 { 988 1008 continue; 989 1009 } 990 1010 991 # The identified span can be ahead of the marker. 992 993 if (isset($Span['position']) and $Span['position'] > $markerPosition) 1011 if (isset($Inline['position']) and $Inline['position'] > $markerPosition) # position is ahead of marker 994 1012 { 995 1013 continue; 996 1014 } 997 1015 998 # Spans that start at the position of their marker don't have to set a position. 999 1000 if ( ! isset($Span['position'])) 1001 { 1002 $Span['position'] = $markerPosition; 1003 } 1004 1005 $plainText = substr($text, 0, $Span['position']); 1006 1007 $markup .= $this->readPlainText($plainText); 1008 1009 $markup .= isset($Span['markup']) ? $Span['markup'] : $this->element($Span['element']); 1010 1011 $text = substr($text, $Span['position'] + $Span['extent']); 1012 1013 $remainder = $text; 1016 if ( ! isset($Inline['position'])) 1017 { 1018 $Inline['position'] = $markerPosition; 1019 } 1020 1021 $unmarkedText = substr($text, 0, $Inline['position']); 1022 1023 $markup .= $this->unmarkedText($unmarkedText); 1024 1025 $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']); 1026 1027 $text = substr($text, $Inline['position'] + $Inline['extent']); 1028 1029 $unexaminedText = $text; 1014 1030 1015 1031 $markerPosition = 0; … … 1018 1034 } 1019 1035 1020 $ remainder= substr($excerpt, 1);1036 $unexaminedText = substr($excerpt, 1); 1021 1037 1022 1038 $markerPosition ++; 1023 1039 } 1024 1040 1025 $markup .= $this-> readPlainText($text);1041 $markup .= $this->unmarkedText($text); 1026 1042 1027 1043 return $markup; … … 1032 1048 # 1033 1049 1034 protected function identifyUrl($Excerpt) 1035 { 1036 if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '/') 1037 { 1038 return; 1039 } 1040 1041 if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) 1042 { 1043 $url = str_replace(array('&', '<'), array('&', '<'), $matches[0][0]); 1050 protected function inlineCode($Excerpt) 1051 { 1052 $marker = $Excerpt['text'][0]; 1053 1054 if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches)) 1055 { 1056 $text = $matches[2]; 1057 $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); 1058 $text = preg_replace("/[ ]*\n/", ' ', $text); 1044 1059 1045 1060 return array( 1046 'extent' => strlen($matches[0][0]), 1047 'position' => $matches[0][1], 1061 'extent' => strlen($matches[0]), 1062 'element' => array( 1063 'name' => 'code', 1064 'text' => $text, 1065 ), 1066 ); 1067 } 1068 } 1069 1070 protected function inlineEmailTag($Excerpt) 1071 { 1072 if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches)) 1073 { 1074 $url = $matches[1]; 1075 1076 if ( ! isset($matches[2])) 1077 { 1078 $url = 'mailto:' . $url; 1079 } 1080 1081 return array( 1082 'extent' => strlen($matches[0]), 1048 1083 'element' => array( 1049 1084 'name' => 'a', 1050 'text' => $ url,1085 'text' => $matches[1], 1051 1086 'attributes' => array( 1052 1087 'href' => $url, … … 1057 1092 } 1058 1093 1059 protected function identifyAmpersand($Excerpt) 1060 { 1061 if ( ! preg_match('/^&#?\w+;/', $Excerpt['text'])) 1094 protected function inlineEmphasis($Excerpt) 1095 { 1096 if ( ! isset($Excerpt['text'][1])) 1097 { 1098 return; 1099 } 1100 1101 $marker = $Excerpt['text'][0]; 1102 1103 if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) 1104 { 1105 $emphasis = 'strong'; 1106 } 1107 elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) 1108 { 1109 $emphasis = 'em'; 1110 } 1111 else 1112 { 1113 return; 1114 } 1115 1116 return array( 1117 'extent' => strlen($matches[0]), 1118 'element' => array( 1119 'name' => $emphasis, 1120 'handler' => 'line', 1121 'text' => $matches[1], 1122 ), 1123 ); 1124 } 1125 1126 protected function inlineEscapeSequence($Excerpt) 1127 { 1128 if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) 1129 { 1130 return array( 1131 'markup' => $Excerpt['text'][1], 1132 'extent' => 2, 1133 ); 1134 } 1135 } 1136 1137 protected function inlineImage($Excerpt) 1138 { 1139 if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') 1140 { 1141 return; 1142 } 1143 1144 $Excerpt['text']= substr($Excerpt['text'], 1); 1145 1146 $Link = $this->inlineLink($Excerpt); 1147 1148 if ($Link === null) 1149 { 1150 return; 1151 } 1152 1153 $Inline = array( 1154 'extent' => $Link['extent'] + 1, 1155 'element' => array( 1156 'name' => 'img', 1157 'attributes' => array( 1158 'src' => $Link['element']['attributes']['href'], 1159 'alt' => $Link['element']['text'], 1160 ), 1161 ), 1162 ); 1163 1164 $Inline['element']['attributes'] += $Link['element']['attributes']; 1165 1166 unset($Inline['element']['attributes']['href']); 1167 1168 return $Inline; 1169 } 1170 1171 protected function inlineLink($Excerpt) 1172 { 1173 $Element = array( 1174 'name' => 'a', 1175 'handler' => 'line', 1176 'text' => null, 1177 'attributes' => array( 1178 'href' => null, 1179 'title' => null, 1180 ), 1181 ); 1182 1183 $extent = 0; 1184 1185 $remainder = $Excerpt['text']; 1186 1187 if (preg_match('/\[((?:[^][]|(?R))*)\]/', $remainder, $matches)) 1188 { 1189 $Element['text'] = $matches[1]; 1190 1191 $extent += strlen($matches[0]); 1192 1193 $remainder = substr($remainder, $extent); 1194 } 1195 else 1196 { 1197 return; 1198 } 1199 1200 if (preg_match('/^[(]((?:[^ ()]|[(][^ )]+[)])+)(?:[ ]+("[^"]*"|\'[^\']*\'))?[)]/', $remainder, $matches)) 1201 { 1202 $Element['attributes']['href'] = $matches[1]; 1203 1204 if (isset($matches[2])) 1205 { 1206 $Element['attributes']['title'] = substr($matches[2], 1, - 1); 1207 } 1208 1209 $extent += strlen($matches[0]); 1210 } 1211 else 1212 { 1213 if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) 1214 { 1215 $definition = strlen($matches[1]) ? $matches[1] : $Element['text']; 1216 $definition = strtolower($definition); 1217 1218 $extent += strlen($matches[0]); 1219 } 1220 else 1221 { 1222 $definition = strtolower($Element['text']); 1223 } 1224 1225 if ( ! isset($this->DefinitionData['Reference'][$definition])) 1226 { 1227 return; 1228 } 1229 1230 $Definition = $this->DefinitionData['Reference'][$definition]; 1231 1232 $Element['attributes']['href'] = $Definition['url']; 1233 $Element['attributes']['title'] = $Definition['title']; 1234 } 1235 1236 $Element['attributes']['href'] = str_replace(array('&', '<'), array('&', '<'), $Element['attributes']['href']); 1237 1238 return array( 1239 'extent' => $extent, 1240 'element' => $Element, 1241 ); 1242 } 1243 1244 protected function inlineMarkup($Excerpt) 1245 { 1246 if ($this->markupEscaped or strpos($Excerpt['text'], '>') === false) 1247 { 1248 return; 1249 } 1250 1251 if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w*[ ]*>/s', $Excerpt['text'], $matches)) 1252 { 1253 return array( 1254 'markup' => $matches[0], 1255 'extent' => strlen($matches[0]), 1256 ); 1257 } 1258 1259 if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches)) 1260 { 1261 return array( 1262 'markup' => $matches[0], 1263 'extent' => strlen($matches[0]), 1264 ); 1265 } 1266 1267 if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches)) 1268 { 1269 return array( 1270 'markup' => $matches[0], 1271 'extent' => strlen($matches[0]), 1272 ); 1273 } 1274 } 1275 1276 protected function inlineSpecialCharacter($Excerpt) 1277 { 1278 if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text'])) 1062 1279 { 1063 1280 return array( … … 1066 1283 ); 1067 1284 } 1068 } 1069 1070 protected function identifyStrikethrough($Excerpt) 1285 1286 $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot'); 1287 1288 if (isset($SpecialCharacter[$Excerpt['text'][0]])) 1289 { 1290 return array( 1291 'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';', 1292 'extent' => 1, 1293 ); 1294 } 1295 } 1296 1297 protected function inlineStrikethrough($Excerpt) 1071 1298 { 1072 1299 if ( ! isset($Excerpt['text'][1])) … … 1088 1315 } 1089 1316 1090 protected function identifyEscapeSequence($Excerpt) 1091 { 1092 if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) 1093 { 1094 return array( 1095 'markup' => $Excerpt['text'][1], 1096 'extent' => 2, 1097 ); 1098 } 1099 } 1100 1101 protected function identifyLessThan() 1102 { 1103 return array( 1104 'markup' => '<', 1105 'extent' => 1, 1106 ); 1107 } 1108 1109 protected function identifyUrlTag($Excerpt) 1110 { 1111 if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(https?:[\/]{2}[^\s]+?)>/i', $Excerpt['text'], $matches)) 1317 protected function inlineUrl($Excerpt) 1318 { 1319 if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') 1320 { 1321 return; 1322 } 1323 1324 if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) 1325 { 1326 $Inline = array( 1327 'extent' => strlen($matches[0][0]), 1328 'position' => $matches[0][1], 1329 'element' => array( 1330 'name' => 'a', 1331 'text' => $matches[0][0], 1332 'attributes' => array( 1333 'href' => $matches[0][0], 1334 ), 1335 ), 1336 ); 1337 1338 return $Inline; 1339 } 1340 } 1341 1342 protected function inlineUrlTag($Excerpt) 1343 { 1344 if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches)) 1112 1345 { 1113 1346 $url = str_replace(array('&', '<'), array('&', '<'), $matches[1]); … … 1126 1359 } 1127 1360 1128 protected function identifyEmailTag($Excerpt) 1129 { 1130 if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\S+?@\S+?)>/', $Excerpt['text'], $matches)) 1131 { 1132 return array( 1133 'extent' => strlen($matches[0]), 1134 'element' => array( 1135 'name' => 'a', 1136 'text' => $matches[1], 1137 'attributes' => array( 1138 'href' => 'mailto:'.$matches[1], 1139 ), 1140 ), 1141 ); 1142 } 1143 } 1144 1145 protected function identifyTag($Excerpt) 1146 { 1147 if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<\/?\w.*?>/', $Excerpt['text'], $matches)) 1148 { 1149 return array( 1150 'markup' => $matches[0], 1151 'extent' => strlen($matches[0]), 1152 ); 1153 } 1154 } 1155 1156 protected function identifyInlineCode($Excerpt) 1157 { 1158 $marker = $Excerpt['text'][0]; 1159 1160 if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/', $Excerpt['text'], $matches)) 1161 { 1162 $text = $matches[2]; 1163 $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); 1164 1165 return array( 1166 'extent' => strlen($matches[0]), 1167 'element' => array( 1168 'name' => 'code', 1169 'text' => $text, 1170 ), 1171 ); 1172 } 1173 } 1174 1175 protected function identifyLink($Excerpt) 1176 { 1177 $extent = $Excerpt['text'][0] === '!' ? 1 : 0; 1178 1179 if (strpos($Excerpt['text'], ']') and preg_match('/\[((?:[^][]|(?R))*)\]/', $Excerpt['text'], $matches)) 1180 { 1181 $Link = array('text' => $matches[1], 'label' => strtolower($matches[1])); 1182 1183 $extent += strlen($matches[0]); 1184 1185 $substring = substr($Excerpt['text'], $extent); 1186 1187 if (preg_match('/^\s*\[([^][]+)\]/', $substring, $matches)) 1188 { 1189 $Link['label'] = strtolower($matches[1]); 1190 1191 if (isset($this->Definitions['Reference'][$Link['label']])) 1192 { 1193 $Link += $this->Definitions['Reference'][$Link['label']]; 1194 1195 $extent += strlen($matches[0]); 1196 } 1197 else 1198 { 1199 return; 1200 } 1201 } 1202 elseif (isset($this->Definitions['Reference'][$Link['label']])) 1203 { 1204 $Link += $this->Definitions['Reference'][$Link['label']]; 1205 1206 if (preg_match('/^[ ]*\[\]/', $substring, $matches)) 1207 { 1208 $extent += strlen($matches[0]); 1209 } 1210 } 1211 elseif (preg_match('/^\([ ]*(.*?)(?:[ ]+[\'"](.+?)[\'"])?[ ]*\)/', $substring, $matches)) 1212 { 1213 $Link['url'] = $matches[1]; 1214 1215 if (isset($matches[2])) 1216 { 1217 $Link['title'] = $matches[2]; 1218 } 1219 1220 $extent += strlen($matches[0]); 1361 # ~ 1362 1363 protected function unmarkedText($text) 1364 { 1365 if ($this->breaksEnabled) 1366 { 1367 $text = preg_replace('/[ ]*\n/', "<br />\n", $text); 1368 } 1369 else 1370 { 1371 $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "<br />\n", $text); 1372 $text = str_replace(" \n", "\n", $text); 1373 } 1374 1375 return $text; 1376 } 1377 1378 # 1379 # Handlers 1380 # 1381 1382 protected function element(array $Element) 1383 { 1384 $markup = '<'.$Element['name']; 1385 1386 if (isset($Element['attributes'])) 1387 { 1388 foreach ($Element['attributes'] as $name => $value) 1389 { 1390 if ($value === null) 1391 { 1392 continue; 1393 } 1394 1395 $markup .= ' '.$name.'="'.$value.'"'; 1396 } 1397 } 1398 1399 if (isset($Element['text'])) 1400 { 1401 $markup .= '>'; 1402 1403 if (isset($Element['handler'])) 1404 { 1405 $markup .= $this->{$Element['handler']}($Element['text']); 1221 1406 } 1222 1407 else 1223 1408 { 1224 return; 1225 } 1409 $markup .= $Element['text']; 1410 } 1411 1412 $markup .= '</'.$Element['name'].'>'; 1226 1413 } 1227 1414 else 1228 1415 { 1229 return; 1230 } 1231 1232 $url = str_replace(array('&', '<'), array('&', '<'), $Link['url']); 1233 1234 if ($Excerpt['text'][0] === '!') 1235 { 1236 $Element = array( 1237 'name' => 'img', 1238 'attributes' => array( 1239 'alt' => $Link['text'], 1240 'src' => $url, 1241 ), 1242 ); 1243 } 1244 else 1245 { 1246 $Element = array( 1247 'name' => 'a', 1248 'handler' => 'line', 1249 'text' => $Link['text'], 1250 'attributes' => array( 1251 'href' => $url, 1252 ), 1253 ); 1254 } 1255 1256 if (isset($Link['title'])) 1257 { 1258 $Element['attributes']['title'] = $Link['title']; 1259 } 1260 1261 return array( 1262 'extent' => $extent, 1263 'element' => $Element, 1264 ); 1265 } 1266 1267 protected function identifyEmphasis($Excerpt) 1268 { 1269 if ( ! isset($Excerpt['text'][1])) 1270 { 1271 return; 1272 } 1273 1274 $marker = $Excerpt['text'][0]; 1275 1276 if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) 1277 { 1278 $emphasis = 'strong'; 1279 } 1280 elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) 1281 { 1282 $emphasis = 'em'; 1283 } 1284 else 1285 { 1286 return; 1287 } 1288 1289 return array( 1290 'extent' => strlen($matches[0]), 1291 'element' => array( 1292 'name' => $emphasis, 1293 'handler' => 'line', 1294 'text' => $matches[1], 1295 ), 1296 ); 1297 } 1298 1299 # 1416 $markup .= ' />'; 1417 } 1418 1419 return $markup; 1420 } 1421 1422 protected function elements(array $Elements) 1423 { 1424 $markup = ''; 1425 1426 foreach ($Elements as $Element) 1427 { 1428 $markup .= "\n" . $this->element($Element); 1429 } 1430 1431 $markup .= "\n"; 1432 1433 return $markup; 1434 } 1435 1300 1436 # ~ 1301 1302 protected function readPlainText($text)1303 {1304 $breakMarker = $this->breaksEnabled ? "\n" : " \n";1305 1306 $text = str_replace($breakMarker, "<br />\n", $text);1307 1308 return $text;1309 }1310 1311 #1312 # ~1313 #1314 1437 1315 1438 protected function li($lines) … … 1333 1456 1334 1457 # 1335 # Multiton 1458 # Deprecated Methods 1459 # 1460 1461 function parse($text) 1462 { 1463 $markup = $this->text($text); 1464 1465 return $markup; 1466 } 1467 1468 # 1469 # Static Methods 1336 1470 # 1337 1471 … … 1353 1487 1354 1488 # 1355 # Deprecated Methods1356 #1357 1358 /**1359 * @deprecated in favor of "text"1360 */1361 function parse($text)1362 {1363 $markup = $this->text($text);1364 1365 return $markup;1366 }1367 1368 #1369 1489 # Fields 1370 1490 # 1371 1491 1372 protected $Definition s;1373 1374 # 1375 # Read- only1492 protected $DefinitionData; 1493 1494 # 1495 # Read-Only 1376 1496 1377 1497 protected $specialCharacters = array( 1378 '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', 1498 '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', 1379 1499 ); 1380 1500 1381 1501 protected $StrongRegex = array( 1382 '*' => '/^[*]{2}((?: [^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',1383 '_' => '/^__((?: [^_]|_[^_]*_)+?)__(?!_)/us',1502 '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s', 1503 '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us', 1384 1504 ); 1385 1505 1386 1506 protected $EmRegex = array( 1387 '*' => '/^[*]((?:[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', 1388 '_' => '/^_((?:[^_]|__[^_]*__)+?)_(?!_)\b/us', 1507 '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', 1508 '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us', 1509 ); 1510 1511 protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?'; 1512 1513 protected $voidElements = array( 1514 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 1389 1515 ); 1390 1516 -
wp-parsedown/trunk/lib/parsedown/README.md
r953966 r1153658 1 1 ## Parsedown 2 2 3 Better [Markdown](http://en.wikipedia.org/wiki/Markdown) parser for PHP. 3 [](https://travis-ci.org/erusev/parsedown) 4 <!--[](https://packagist.org/packages/erusev/parsedown)--> 4 5 5 * [Demo](http://parsedown.org/demo) 6 * [Test Suite](http://parsedown.org/tests/) 6 Better Markdown Parser in PHP 7 8 [See Demo](http://parsedown.org/demo) 7 9 8 10 ### Features … … 10 12 * [Fast](http://parsedown.org/speed) 11 13 * [Consistent](http://parsedown.org/consistency) 12 * [GitHub Flavored](https://help.github.com/articles/github-flavored-markdown) 13 * [Tested](https://travis-ci.org/erusev/parsedown) in PHP 5.2, 5.3, 5.4, 5.5, 5.6 and [hhvm](http://www.hhvm.com/) 14 * Extensible 15 * [Markdown Extra extension](https://github.com/erusev/parsedown-extra) <sup>new</sup> 16 * [JavaScript port](https://github.com/hkdobrev/parsedown.js) under development <sup>new</sup> 14 * [GitHub flavored](https://help.github.com/articles/github-flavored-markdown) 15 * [Tested](http://parsedown.org/tests/) in PHP 5.3, 5.4, 5.5, 5.6 and [HHVM](http://www.hhvm.com/) 16 * [Extensible](https://github.com/erusev/parsedown/wiki/Writing-Extensions) 17 * [Markdown Extra extension](https://github.com/erusev/parsedown-extra) 17 18 18 19 ### Installation … … 28 29 ``` 29 30 30 More examples in [the wiki](https://github.com/erusev/parsedown/wiki/Usage) .31 More examples in [the wiki](https://github.com/erusev/parsedown/wiki/Usage) and in [this video tutorial](http://youtu.be/wYZBY8DEikI). 31 32 32 33 ### Questions 33 34 34 **How does Parsedown work?**<br/> 35 Parsedown recognises that the Markdown syntax is optimised for humans so it tries to read like one. It goes through text line by line. It looks at how lines start to identify blocks. It looks for special characters to identify inline elements. 35 **How does Parsedown work?** 36 36 37 **Why doesn’t Parsedown use namespaces?**<br/> 38 Using namespaces would mean dropping support for PHP 5.2. Since Parsedown is a single class with an uncommon name, making this trade wouldn't make much sense. 37 It tries to read Markdown like a human. First, it looks at the lines. It’s interested in how the lines start. This helps it recognise blocks. It knows, for example, that if a line start with a `-` then it perhaps belong to a list. Once it recognises the blocks, it continues to the content. As it reads, it watches out for special characters. This helps it recognise inline elements (or inlines). 39 38 40 **Who uses Parsedown?**<br/> 41 [phpDocumentor](http://www.phpdoc.org/), [Bolt CMS](http://bolt.cm/), [RaspberryPi.org](http://www.raspberrypi.org/) and [more](https://www.versioneye.com/php/erusev:parsedown/references). 39 We call this approach "line based". We believe that Parsedown is the first Markdown parser to use it. Since the release of Parsedown, other developers have used the same approach to develop other Markdown parsers in PHP and in other languages. 40 41 **Is it compliant with CommonMark?** 42 43 It passes most of the CommonMark tests. Most of the tests that don't pass deal with cases that are quite uncommon. Still, as CommonMark matures, compliance should improve. 44 45 **Who uses it?** 46 47 [phpDocumentor](http://www.phpdoc.org/), [October CMS](http://octobercms.com/), [Bolt CMS](http://bolt.cm/), [Kirby CMS](http://getkirby.com/), [Grav CMS](http://getgrav.org/), [Statamic CMS](http://www.statamic.com/), [RaspberryPi.org](http://www.raspberrypi.org/) and [more](https://www.versioneye.com/php/erusev:parsedown/references). 48 49 **How can I help?** 50 51 Use it, star it, share it and if you feel generous, [donate some money](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2). -
wp-parsedown/trunk/readme.txt
r982893 r1153658 4 4 Tags: markdown, editor, parsedown 5 5 Requires at least: 3.0 6 Tested up to: 4. 07 Stable tag: 0. 1.16 Tested up to: 4.2.1 7 Stable tag: 0.3 8 8 License: GPLv3 9 9 License URI: http://www.gnu.org/licenses/gpl-3.0.html … … 23 23 == Changelog == 24 24 25 = 0.3 = 26 *2015-05-05* 27 28 * updating Parsedown and Parsedown Extra libraries 29 * removing wp-common dependancy 30 * changing debug log method 31 32 = 0.2 = 33 *2014-09-23* 34 35 * added removal of wpautop filters; they are not needed when Parsedown is doing it's job 36 * updated parsedown libs 37 25 38 = 0.1.1 = 26 39 *2014-09-06* -
wp-parsedown/trunk/wp-parsedown.php
r982893 r1153658 4 4 Plugin URI: https://github.com/petermolnar/wp-parsedown 5 5 Description: [Parsedown Extra](www.parsedown.org/demo?extra=1) on-the-fly 6 Version: 0. 1.16 Version: 0.3 7 7 Author: Peter Molnar <[email protected]> 8 8 Author URI: https://petermolnar.eu/ … … 13 13 if ( ! class_exists( 'WP_PARSEDOWN' ) ) : 14 14 15 /* get the plugin abstract class*/16 include_once ( dirname(__FILE__) . '/wp-common/plugin_abstract.php' );17 15 include_once ( dirname(__FILE__) . '/lib/parsedown/Parsedown.php'); 18 16 include_once ( dirname(__FILE__) . '/lib/parsedown-extra/ParsedownExtra.php'); … … 21 19 * main wp-ghost class 22 20 */ 23 class WP_PARSEDOWN extends PluginAbstract { 24 const key_save = 'saved'; 25 const key_delete = 'deleted'; 26 private $parsedown = null; 21 class WP_PARSEDOWN { 27 22 28 /** 29 * 30 */ 31 public function plugin_post_construct () { 32 $this->plugin_url = plugin_dir_url( __FILE__ ); 33 $this->plugin_dir = plugin_dir_path( __FILE__ ); 34 35 $this->common_url = $this->plugin_url . self::common_slug; 36 $this->common_dir = $this->plugin_dir . self::common_slug; 37 38 $this->admin_css_handle = $this->plugin_constant . '-admin-css'; 39 $this->admin_css_url = $this->common_url . 'wp-admin.css'; 40 41 $this->parsedown = new ParsedownExtra(); 23 public function __construct () { 24 add_action( 'init', array(&$this,'init')); 42 25 } 43 26 44 /** 45 * init hook function runs before admin panel hook, themeing and options read 46 */ 47 public function plugin_pre_init() { 48 27 public function init () { 28 remove_filter( 'the_content', 'wpautop' ); 29 remove_filter( 'the_excerpt', 'wpautop' ); 30 add_filter( 'the_content', array( &$this, 'parsedown'), 8, 1 ); 49 31 } 50 32 51 /** 52 * additional init, steps that needs the plugin options 53 * 54 */ 55 public function plugin_post_init () { 56 /* display markdown */ 57 add_filter( 'the_content', array(&$this, 'markdown_on_the_fly'), 9 ); 33 public function parsedown ( $markdown ) { 34 $post = get_post(); 58 35 59 } 60 61 62 /** 63 * activation hook function, to be extended 64 */ 65 public function plugin_activate() { 66 /* we leave this empty to avoid not detecting WP network correctly */ 67 } 68 69 /** 70 * deactivation hook function, to be extended 71 */ 72 public function plugin_deactivate () { 73 } 74 75 /** 76 * uninstall hook function, to be extended 77 */ 78 public function plugin_uninstall( $delete_options = true ) { 79 } 80 81 /** 82 * extending admin init 83 * 84 */ 85 public function plugin_extend_admin_init () { 86 } 87 88 /** 89 * admin help panel 90 */ 91 public function plugin_admin_help($contextual_help, $screen_id ) { 92 93 /* add our page only if the screenid is correct */ 94 if ( strpos( $screen_id, $this->plugin_settings_page ) ) { 95 $contextual_help = __('<p>Please visit <a href="http://wordpress.org/support/plugin/wp-ghost">the official support forum of the plugin</a> for help.</p>', $this->plugin_constant ); 36 if ( defined( 'WP_DEBUG' ) && WP_DEBUG == true ) { 37 $message = sprintf ( __('parsing post: %s', $this->plugin_constant), $post->ID ); 38 error_log( __CLASS__ . ": " . $message ); 96 39 } 97 40 98 return $contextual_help; 99 } 100 101 /** 102 * admin panel, the admin page displayed for plugin settings 103 */ 104 public function plugin_admin_panel() { 105 /** 106 * security, if somehow we're running without WordPress security functions 107 */ 108 if( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ){ 109 die( ); 110 } 111 ?> 112 113 <div class="wrap"> 114 115 <script> 116 jQuery(document).ready(function($) { 117 jQuery( "#<?php echo $this->plugin_constant ?>-settings" ).tabs(); 118 }); 119 </script> 120 121 <?php 122 123 /* display donation form */ 124 //$this->plugin_donation_form(); 125 126 /** 127 * if options were saved, display saved message 128 */ 129 if (isset($_GET[ self::key_save ]) && $_GET[ self::key_save ]=='true' || $this->status == 1) { ?> 130 <div class='updated settings-error'><p><strong><?php _e( 'Settings saved.' , $this->plugin_constant ) ?></strong></p></div> 131 <?php } 132 133 /** 134 * if options were delete, display delete message 135 */ 136 if (isset($_GET[ self::key_delete ]) && $_GET[ self::key_delete ]=='true' || $this->status == 2) { ?> 137 <div class='error'><p><strong><?php _e( 'Plugin options deleted.' , $this->plugin_constant ) ?></strong></p></div> 138 <?php } 139 140 /** 141 * the admin panel itself 142 */ 143 ?> 144 145 <h2><?php printf ( __( '%s settings', $this->plugin_constant ), $this->plugin_name ) ; ?></h2> 146 147 <form autocomplete="off" method="post" action="#" id="<?php echo $this->plugin_constant ?>-settings" class="plugin-admin"> 148 149 <?php wp_nonce_field( $this->plugin_constant ); ?> 150 <ul class="tabs"> 151 <li><a href="#<?php echo $this->plugin_constant ?>-general" class="wp-switch-editor"><?php _e( 'Generic settings', $this->plugin_constant ); ?></a></li> 152 </ul> 153 154 <fieldset id="<?php echo $this->plugin_constant ?>-general"> 155 <legend><?php _e( 'General settings', $this->plugin_constant ); ?></legend> 156 <dl> 157 <dt> 158 <label for="debug"><?php _e("Enable debug logging?", $this->plugin_constant); ?></label> 159 </dt> 160 <dd> 161 <input type="checkbox" name="debug" id="debug" value="1" <?php checked($this->options['debug'],true); ?> /> 162 <span class="description"><?php _e('Enables log messages; if <a href="http://codex.wordpress.org/WP_DEBUG">WP_DEBUG</a> is enabled, notices and info level is displayed as well, otherwie only ERRORS are logged.', $this->plugin_constant); ?></span> 163 </dd> 164 </dl> 165 </fieldset> 166 <p class="clear"> 167 <input class="button-primary" type="submit" name="<?php echo $this->button_save ?>" id="<?php echo $this->button_save ?>" value="<?php _e('Save Changes', $this->plugin_constant ) ?>" /> 168 </p> 169 </form> 170 </div> 171 <?php 172 } 173 174 /** 175 * extending options_save 176 * 177 */ 178 public function plugin_extend_options_save( $activating ) { 179 } 180 181 /** 182 * read hook; needs to be implemented 183 */ 184 public function plugin_extend_options_read( &$options ) { 185 } 186 187 /** 188 * options delete hook; needs to be implemented 189 */ 190 public function plugin_extend_options_delete( ) { 191 } 192 193 /** 194 * need to do migrations from previous versions of the plugin 195 * 196 */ 197 public function plugin_options_migrate( &$options ) { 198 } 199 200 201 202 /** 203 * log wrapper to include options 204 * 205 */ 206 public function log ( $message, $log_level = LOG_WARNING ) { 207 if ( !isset ( $this->options['debug'] ) || $this->options['debug'] != 1 ) 208 return false; 209 else 210 $this->utils->log ( $this->plugin_constant, $message, $log_level ); 211 } 212 213 /** 214 * 215 */ 216 public function markdown_on_the_fly ( $markdown ) { 217 $post = get_post(); 218 $this->log ( sprintf ( __('parsing post: %s', $this->plugin_constant), $post->ID ) ); 219 return $this->parsedown->text ( $markdown ); 41 $parsedown = new ParsedownExtra(); 42 $parsedown->setBreaksEnabled(true); 43 return $parsedown->text ( $markdown ); 220 44 } 221 45 222 46 } 223 47 48 $wp_parsedown = new WP_PARSEDOWN (); 49 224 50 endif; 225 226 227 $wp_parsedown_defaults = array (228 'debug' => 0,229 );230 231 $wp_parsedown = new WP_PARSEDOWN ( 'wp-parsedown', '0.1', 'WP-Parsedown', $wp_parsedown_defaults );232 233 234 ?>
Note: See TracChangeset
for help on using the changeset viewer.