1<?php 2/** 3 * PHP Markdown Extra plugin for DokuWiki. 4 * 5 * @license GPL 3 (http://www.gnu.org/licenses/gpl.html) - NOTE: PHP Markdown 6 * Extra is licensed under the BSD license. See License.text for details. 7 * @version 1.03 - 24.11.2012 - PHP Markdown Extra 1.2.5 included. 8 * @author Joonas Pulakka <joonas.pulakka@iki.fi>, Jiang Le <smartynaoki@gmail.com> 9 */ 10 11if (!defined('DOKU_INC')) die(); 12if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/'); 13require_once (DOKU_PLUGIN . 'syntax.php'); 14require_once (DOKU_PLUGIN . 'markdownextra/markdown.php'); 15 16class syntax_plugin_markdownextra extends DokuWiki_Syntax_Plugin { 17 18 function getType() { 19 return 'protected'; 20 } 21 22 function getPType() { 23 return 'block'; 24 } 25 26 function getSort() { 27 return 69; 28 } 29 30 function connectTo($mode) { 31 $this->Lexer->addEntryPattern('<markdown>(?=.*</markdown>)', $mode, 'plugin_markdownextra'); 32 } 33 34 function postConnect() { 35 $this->Lexer->addExitPattern('</markdown>', 'plugin_markdownextra'); 36 } 37 38 function handle($match, $state, $pos, Doku_Handler $handler) { 39 switch ($state) { 40 case DOKU_LEXER_ENTER : return array($state, ''); 41 case DOKU_LEXER_UNMATCHED : return array($state, Markdown($match)); 42 case DOKU_LEXER_EXIT : return array($state, ''); 43 } 44 return array($state,''); 45 } 46 47 function render($mode, Doku_Renderer $renderer, $data) { 48 //dbg('function render($mode, &$renderer, $data)-->'.' mode = '.$mode.' data = '.$data); 49 //dbg($data); 50 if ($mode == 'xhtml') { 51 list($state,$match) = $data; 52 switch ($state) { 53 case DOKU_LEXER_ENTER : break; 54 case DOKU_LEXER_UNMATCHED : 55 $match = $this->_toc($renderer, $match); 56 $renderer->doc .= $match; 57 break; 58 case DOKU_LEXER_EXIT : break; 59 } 60 return true; 61 }else if ($mode == 'metadata') { 62 //dbg('function render($mode, &$renderer, $data)-->'.' mode = '.$mode.' data = '.$data); 63 //dbg($data); 64 list($state,$match) = $data; 65 switch ($state) { 66 case DOKU_LEXER_ENTER : break; 67 case DOKU_LEXER_UNMATCHED : 68 if (!$renderer->meta['title']){ 69 $renderer->meta['title'] = $this->_markdown_header($match); 70 } 71 $this->_toc($renderer, $match); 72 $internallinks = $this->_internallinks($match); 73 #dbg($internallinks); 74 if (count($internallinks)>0){ 75 foreach($internallinks as $internallink) 76 { 77 $renderer->internallink($internallink); 78 } 79 } 80 break; 81 case DOKU_LEXER_EXIT : break; 82 } 83 return true; 84 } else { 85 return false; 86 } 87 } 88 89 function _markdown_header($text) 90 { 91 $doc = new DOMDocument('1.0','UTF-8'); 92 //dbg($doc); 93 $meta = '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>'; 94 $doc->loadHTML($meta.$text); 95 //dbg($doc->saveHTML()); 96 if ($nodes = $doc->getElementsByTagName('h1')){ 97 return $nodes->item(0)->nodeValue; 98 } 99 return false; 100 } 101 102 function _internallinks($text) 103 { 104 $links = array(); 105 if ( ! $text ) return $links; 106 $doc = new DOMDocument('1.0', 'UTF-8'); 107 $doc->loadHTML($text); 108 if ($nodes = $doc->getElementsByTagName('a')){ 109 foreach($nodes as $atag) 110 { 111 $href = $atag->getAttribute('href'); 112 if (!preg_match('/^(https{0,1}:\/\/|ftp:\/\/|mailto:)/i',$href)){ 113 $links[] = $href; 114 } 115 } 116 } 117 return $links; 118 } 119 120 function _toc(&$renderer, $text) 121 { 122 $doc = new DOMDocument('1.0','UTF-8'); 123 //dbg($doc); 124 $meta = '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>'; 125 $doc->loadHTML($meta.$text); 126 if ($nodes = $doc->getElementsByTagName("*")){ 127 foreach($nodes as $node) 128 { 129 if (preg_match('/h([1-7])/',$node->tagName,$match)) 130 { 131 #dbg($node); 132 $node->setAttribute('class', 'sectionedit'.$match[1]); 133 $hid = $renderer->_headerToLink($node->nodeValue,'true'); 134 $node->setAttribute('id',$hid); 135 $renderer->toc_additem($hid, $node->nodeValue, $match[1]); 136 } 137 138 } 139 } 140 //remove outer tags of content 141 $html = $doc->saveHTML(); 142 $html = str_replace('<!DOCTYPE html>','',$html); 143 $html = preg_replace('/.+<body>/', '', $html); 144 $html = preg_replace('@</body>.*</html>@','', $html); 145 return $html; 146 } 147 148}