2 /*=====================================================================*\
3 || ###################################################################
4 || # Blue Static ISSO Framework
5 || # Copyright ©2002-[#]year[#] Blue Static
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
22 require_once('ISSO/Functions.php');
27 * This class is a PHP implementation of John Gruber's Markdown text processing
28 * system. It is not a port of his Perl version, but rather a creation based
29 * on the rules outlined here: http://daringfireball.net/projects/markdown/.
32 * @copyright Copyright (c)2002 - [#]year[#], Blue Static
40 * Remove HTML rather than ignoring it?
43 public $removeHtml = false
;
46 * Map of HTML blocks extracted from the text
49 private $htmlBlockMap = array();
52 * The working parser text that at any given moment is only partially parsed
58 * HTML block element tags
61 private $htmlBockTags = array(
62 'p', 'div', 'blockquote',
63 'pre', 'table', 'form', 'ol',
64 'ul', 'h1', 'h2', 'h3', 'h4',
65 'h5', 'h6', 'iframe', 'script',
69 // ###################################################################
71 * Quick parsing function that uses the system defaults for parsing.
73 * @param string Original text
75 * @return string HTML output
77 public static function Parse($text)
79 $parser = new BSMarkdown();
80 return $parser->transform($text);
83 // ###################################################################
87 public function __construct()
89 $this->htmlBlockMap
= array();
93 // ###################################################################
95 * Transforms the Markdown text into XHTML with the parser's set options
97 * @param string Text to transform
99 * @return string HTML output
101 public function transform($text)
103 // reset the data arrays
104 $this->__construct();
106 // convert line breaks and remove empty lines of whitespace
107 $this->text
= BSFunctions
::ConvertLineBreaks($text);
108 $this->text
= preg_replace('/^\s*?$/m', '', $this->text
);
110 $this->_extractHtmlBlocks();
112 $this->_convertHardLineBreaks();
113 $this->_convertAtxHeaders();
114 $this->_convertSetextHeaders();
115 $this->_formatParagraphs();
116 $this->text
= $this->_expandHtmlBlocks($this->text
);
119 $this->_convertFloatingEntities();
124 // ###################################################################
126 * Description of the function
128 * @param string A string param
130 * @return integer Return value
132 private function _extractHtmlBlocks()
139 // find the first insance of a block tag
140 $regex = implode('|', $this->htmlBockTags
);
141 while ($start <= strlen($this->text
))
144 if (preg_match("/^<($regex)/i", substr($this->text
, $start)) === 1)
146 if (sizeof($nest) == 0)
148 $blockStart = $start;
150 array_push($nest, $start);
152 else if (preg_match("#^</($regex)>#i", substr($this->text
, $start), $matches) === 1)
155 if (sizeof($nest) == 0)
157 $block = substr($this->text
, $blockStart, $start - $blockStart +
strlen($matches[0]));
158 $hash = md5($block . microtime());
159 $this->htmlBlockMap
[$hash] = $block;
160 $this->text
= substr_replace($this->text
, $hash, $blockStart, strlen($block));
161 $start = $blockStart;
167 // ###################################################################
169 * Expands the hashed HTML blocks back into their originial form
171 private function _expandHtmlBlocks($text)
173 return str_replace(array_keys($this->htmlBlockMap
), array_values($this->htmlBlockMap
), $text);
176 // ###################################################################
178 * Converts text surrounded by #sings to headers (## Heading 2)
180 private function _convertAtxHeaders()
182 $this->text
= preg_replace_callback('/^(\#{1,6})\s*(.+)(\s*\#+)?$/', array(&$this, '_convertAtxHeadersCallback'), $this->text
);
185 // ###################################################################
187 * Callback function for preg_replace() in _convertAtxHeaders()
189 * @param array Matches
191 private function _convertAtxHeadersCallback($matches)
194 $html = '<h' . strlen($matches[1]) . '>' . $this->_expandHtmlBlocks($matches[2]) . '</h' . strlen($matches[1]) . '>';
195 $hash = md5($html . microtime());
196 $this->htmlBlockMap
[$hash] = $html;
200 // ###################################################################
202 * Converts headers that are formed by underlines into headings
204 private function _convertSetextHeaders()
206 $this->text
= preg_replace_callback('/(.+)\n(-|=){1,}$/m', array(&$this, '_convertSetextHeadersCallback'), $this->text
);
209 // ###################################################################
211 * Callback function for _convertSetextHeaders(). This does the actual
212 * conversion and then hashes it into a block
214 * @param array Matches from the preg_replace_callback()
216 private function _convertSetextHeadersCallback($matches)
218 $text = $this->_expandHtmlBlocks($matches[1]);
219 if ($matches[2][0] == '=')
221 $text = '<h1>' . $text . '</h1>';
225 $text = '<h2>' . $text . '</h2>';
227 $hash = md5($text . microtime());
228 $this->htmlBlockMap
[$hash] = $text;
232 // ###################################################################
234 * Wraps blocks into paragraphs
236 private function _formatParagraphs()
238 $blocks = preg_split('/\n{2,}/', $this->text
, -1, PREG_SPLIT_NO_EMPTY
);
239 foreach ($blocks AS $key => $value)
241 if (!isset($this->htmlBlockMap
[$value]))
243 $blocks[$key] = "<p>$value</p>";
247 $this->text
= implode("\n\n", $blocks);
250 // ###################################################################
252 * Converts two spaces followed by a new line with text on it to
253 * a hard line break (<br />)
255 private function _convertHardLineBreaks()
257 $this->text
= preg_replace('/ {2,}\n/m', " <br />\n", $this->text
);
260 // ###################################################################
262 * Converts all angle brackets and ampersands that are floating into
265 private function _convertFloatingEntities()
268 $this->text
= preg_replace('/&(?!#?x?[0-9a-z]+;)/i', '&', $this->text
);
270 // encode brackets who aren't followed by text
271 $this->text
= preg_replace('#<(?![/?a-z])#i', '<', $this->text
);
275 /*=====================================================================*\
276 || ###################################################################
279 || ###################################################################
280 \*=====================================================================*/