From 5f33d9a6a4bd36084f1526416c97072dc42ccf46 Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <sbrl@starbeamrainbowlabs.com>
Date: Wed, 27 May 2015 10:32:13 +0100
Subject: [PATCH] Moved markdown parser to a module

---
 core.php                   | 122 ++---------------
 index.php                  | 260 ++++++++++++++++++++-----------------
 module_index.json          |  12 +-
 modules/page-view.php      |  10 +-
 modules/parser-default.php | 127 ++++++++++++++++++
 5 files changed, 297 insertions(+), 234 deletions(-)
 create mode 100644 modules/parser-default.php

diff --git a/core.php b/core.php
index 37ad64a..07f1b22 100644
--- a/core.php
+++ b/core.php
@@ -316,117 +316,6 @@ class page_renderer
 	}
 }
 
-////////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////// Slimdown /////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////// %slimdown% //
-////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Slimdown - A very basic regex-based Markdown parser. Supports the
- * following elements (and can be extended via Slimdown::add_rule()):
- *
- * - Headers
- * - Links
- * - Bold
- * - Emphasis
- * - Deletions
- * - Quotes
- * - Inline code
- * - Blockquotes
- * - Ordered/unordered lists
- * - Horizontal rules
- *
- * Author: Johnny Broadway <johnny@johnnybroadway.com>
- * Website: https://gist.github.com/jbroadway/2836900
- * License: MIT
- */
-
-/**
- * Modified by Starbeamrainbowlabs (starbeamrainbowlabs)
- * 
- 	* Changed bold to use single asterisks
- 	* Changed italics to use single underscores
- 	* Added one to add the heading levels (no <h1> tags allowed)
- 	* Added wiki style internal link parsing
- 	* Added wiki style internal link parsing with display text
- */
-class Slimdown {
-	public static $rules = array (
-		'/\r\n/' => "\n",											// new line normalisation
-		'/(#+)(.*)/' => 'self::header',								// headers
-		'/(\*)(.*?)\1/' => '<strong>\2</strong>',					// bold
-		'/(_)(.*?)\1/' => '<em>\2</em>',							// emphasis
-		
-		// todo test these
-		'/!\[(.*)\]\(([^\s]+)\s(\d+.+)\s(left|right)\)/' => '<img src="\2" alt="\1" style="max-width: \3; float: \4;" />',		// images with size
-		'/!\[(.*)\]\(([^\s]+)\s(\d+.+)\)/' => '<img src="\2" alt="\1" style="max-width: \3;" />',		// images with size
-		'/!\[(.*)\]\((.*)\)/' => '<img src="\2" alt="\1" />',		// basic images
-		// todo end
-		
-		'/\[\[([a-zA-Z0-9\_\- ]+)\|([a-zA-Z0-9\_\- ]+)\]\]/' => '<a href=\'index.php?page=\1\'>\2</a>',	//internal links with display text
-		'/\[\[([a-zA-Z0-9\_\- ]+)\]\]/' => '<a href=\'index.php?page=\1\'>\1</a>',	//internal links
-		'/\[([^\[]+)\]\(([^\)]+)\)/' => '<a href=\'\2\' target=\'_blank\'>\1</a>',	// links
-		'/\~\~(.*?)\~\~/' => '<del>\1</del>',						// del
-		'/\:\"(.*?)\"\:/' => '<q>\1</q>',							// quote
-		'/`(.*?)`/' => '<code>\1</code>',							// inline code
-		'/\n\s*(\*|-)(.*)/' => 'self::ul_list',							// ul lists
-		'/\n[0-9]+\.(.*)/' => 'self::ol_list',						// ol lists
-		'/\n(&gt;|\>)(.*)/' => 'self::blockquote',					// blockquotes
-		'/\n-{3,}/' => "\n<hr />",									// horizontal rule
-		'/\n([^\n]+)\n\n/' => 'self::para',							// add paragraphs
-		'/<\/ul>\s?<ul>/' => '',									// fix extra ul
-		'/<\/ol>\s?<ol>/' => '',									// fix extra ol
-		'/<\/blockquote><blockquote>/' => "\n"						// fix extra blockquote
-	);
-	private static function para ($regs) {
-		$line = $regs[1];
-		$trimmed = trim ($line);
-		if (preg_match ('/^<\/?(ul|ol|li|h|p|bl)/', $trimmed)) {
-			return "\n" . $line . "\n";
-		}
-		return sprintf ("\n<p>%s</p>\n", $trimmed);
-	}
-	private static function ul_list ($regs) {
-		$item = $regs[2];
-		return sprintf ("\n<ul>\n\t<li>%s</li>\n</ul>", trim($item));
-	}
-	private static function ol_list ($regs) {
-		$item = $regs[1];
-		return sprintf ("\n<ol>\n\t<li>%s</li>\n</ol>", trim($item));
-	}
-	private static function blockquote ($regs) {
-		$item = $regs[2];
-		return sprintf ("\n<blockquote>%s</blockquote>", trim($item));
-	}
-	private static function header ($regs) {
-		list ($tmp, $chars, $header) = $regs;
-		$level = strlen ($chars);
-		return sprintf ('<h%d>%s</h%d>', $level + 1, trim($header), $level + 1);
-	}
-	
-	/**
-	 * Add a rule.
-	 */
-	public static function add_rule ($regex, $replacement) {
-		self::$rules[$regex] = $replacement;
-	}
-	/**
-	 * Render some Markdown into HTML.
-	 */
-	public static function render ($text) {
-		foreach (self::$rules as $regex => $replacement) {
-			if (is_callable ( $replacement)) {
-				$text = preg_replace_callback ($regex, $replacement, $text);
-			} else {
-				$text = preg_replace ($regex, $replacement, $text);
-			}
-		}
-		return trim ($text);
-	}
-}
-////////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////
-
 ///////////////////////////////////////////
 //////////////// Functions ////////////////
 ///////////////////////////////////////////
@@ -486,6 +375,17 @@ function add_action($action_name, $func)
 	$actions->$action_name = $func;
 }
 
+// Function to register a new parser. If multiple parsers are registered then
+// only the last parser registered will actually be used.
+$parse_page_source = function() {
+	throw new Exception("No parser registered!");
+};
+function add_parser($parser_code)
+{
+	global $parse_page_source;
+	$parse_page_source = $parser_code;
+}
+
 //////////////////////////////////////////////////////////////////
 
 
diff --git a/index.php b/index.php
index f6f763d..b344f35 100644
--- a/index.php
+++ b/index.php
@@ -470,117 +470,6 @@ class page_renderer
 	}
 }
 
-////////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////// Slimdown /////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////// %slimdown% //
-////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Slimdown - A very basic regex-based Markdown parser. Supports the
- * following elements (and can be extended via Slimdown::add_rule()):
- *
- * - Headers
- * - Links
- * - Bold
- * - Emphasis
- * - Deletions
- * - Quotes
- * - Inline code
- * - Blockquotes
- * - Ordered/unordered lists
- * - Horizontal rules
- *
- * Author: Johnny Broadway <johnny@johnnybroadway.com>
- * Website: https://gist.github.com/jbroadway/2836900
- * License: MIT
- */
-
-/**
- * Modified by Starbeamrainbowlabs (starbeamrainbowlabs)
- * 
- 	* Changed bold to use single asterisks
- 	* Changed italics to use single underscores
- 	* Added one to add the heading levels (no <h1> tags allowed)
- 	* Added wiki style internal link parsing
- 	* Added wiki style internal link parsing with display text
- */
-class Slimdown {
-	public static $rules = array (
-		'/\r\n/' => "\n",											// new line normalisation
-		'/(#+)(.*)/' => 'self::header',								// headers
-		'/(\*)(.*?)\1/' => '<strong>\2</strong>',					// bold
-		'/(_)(.*?)\1/' => '<em>\2</em>',							// emphasis
-		
-		// todo test these
-		'/!\[(.*)\]\(([^\s]+)\s(\d+.+)\s(left|right)\)/' => '<img src="\2" alt="\1" style="max-width: \3; float: \4;" />',		// images with size
-		'/!\[(.*)\]\(([^\s]+)\s(\d+.+)\)/' => '<img src="\2" alt="\1" style="max-width: \3;" />',		// images with size
-		'/!\[(.*)\]\((.*)\)/' => '<img src="\2" alt="\1" />',		// basic images
-		// todo end
-		
-		'/\[\[([a-zA-Z0-9\_\- ]+)\|([a-zA-Z0-9\_\- ]+)\]\]/' => '<a href=\'index.php?page=\1\'>\2</a>',	//internal links with display text
-		'/\[\[([a-zA-Z0-9\_\- ]+)\]\]/' => '<a href=\'index.php?page=\1\'>\1</a>',	//internal links
-		'/\[([^\[]+)\]\(([^\)]+)\)/' => '<a href=\'\2\' target=\'_blank\'>\1</a>',	// links
-		'/\~\~(.*?)\~\~/' => '<del>\1</del>',						// del
-		'/\:\"(.*?)\"\:/' => '<q>\1</q>',							// quote
-		'/`(.*?)`/' => '<code>\1</code>',							// inline code
-		'/\n\s*(\*|-)(.*)/' => 'self::ul_list',							// ul lists
-		'/\n[0-9]+\.(.*)/' => 'self::ol_list',						// ol lists
-		'/\n(&gt;|\>)(.*)/' => 'self::blockquote',					// blockquotes
-		'/\n-{3,}/' => "\n<hr />",									// horizontal rule
-		'/\n([^\n]+)\n\n/' => 'self::para',							// add paragraphs
-		'/<\/ul>\s?<ul>/' => '',									// fix extra ul
-		'/<\/ol>\s?<ol>/' => '',									// fix extra ol
-		'/<\/blockquote><blockquote>/' => "\n"						// fix extra blockquote
-	);
-	private static function para ($regs) {
-		$line = $regs[1];
-		$trimmed = trim ($line);
-		if (preg_match ('/^<\/?(ul|ol|li|h|p|bl)/', $trimmed)) {
-			return "\n" . $line . "\n";
-		}
-		return sprintf ("\n<p>%s</p>\n", $trimmed);
-	}
-	private static function ul_list ($regs) {
-		$item = $regs[2];
-		return sprintf ("\n<ul>\n\t<li>%s</li>\n</ul>", trim($item));
-	}
-	private static function ol_list ($regs) {
-		$item = $regs[1];
-		return sprintf ("\n<ol>\n\t<li>%s</li>\n</ol>", trim($item));
-	}
-	private static function blockquote ($regs) {
-		$item = $regs[2];
-		return sprintf ("\n<blockquote>%s</blockquote>", trim($item));
-	}
-	private static function header ($regs) {
-		list ($tmp, $chars, $header) = $regs;
-		$level = strlen ($chars);
-		return sprintf ('<h%d>%s</h%d>', $level + 1, trim($header), $level + 1);
-	}
-	
-	/**
-	 * Add a rule.
-	 */
-	public static function add_rule ($regex, $replacement) {
-		self::$rules[$regex] = $replacement;
-	}
-	/**
-	 * Render some Markdown into HTML.
-	 */
-	public static function render ($text) {
-		foreach (self::$rules as $regex => $replacement) {
-			if (is_callable ( $replacement)) {
-				$text = preg_replace_callback ($regex, $replacement, $text);
-			} else {
-				$text = preg_replace ($regex, $replacement, $text);
-			}
-		}
-		return trim ($text);
-	}
-}
-////////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////
-
 ///////////////////////////////////////////
 //////////////// Functions ////////////////
 ///////////////////////////////////////////
@@ -640,6 +529,17 @@ function add_action($action_name, $func)
 	$actions->$action_name = $func;
 }
 
+// Function to register a new parser. If multiple parsers are registered then
+// only the last parser registered will actually be used.
+$parse_page_source = function() {
+	throw new Exception("No parser registered!");
+};
+function add_parser($parser_code)
+{
+	global $parse_page_source;
+	$parse_page_source = $parser_code;
+}
+
 //////////////////////////////////////////////////////////////////
 
 
@@ -1202,13 +1102,13 @@ register_module([
 
 register_module([
 	"name" => "Page viewer",
-	"version" => "0.6",
+	"version" => "0.7",
 	"author" => "Starbeamrainbowlabs",
 	"description" => "Allows you to view pages. You should include this one.",
 	"id" => "page-view",
 	"code" => function() {
 		add_action("view", function() {
-			global $pageindex, $settings, $page;
+			global $pageindex, $settings, $page, $parse_page_source;
 			
 			//check to make sure that the page exists
 			if(!isset($pageindex->$page))
@@ -1231,11 +1131,11 @@ register_module([
 			$title = "$page - $settings->sitename";
 			$content = "<h1>$page</h1>";
 			
-			$slimdown_start = microtime(true);
+			$parsing_start = microtime(true);
 			
-			$content .= Slimdown::render(file_get_contents("$page.md"));
+			$content .= $parse_page_source(file_get_contents("$page.md"));
 			
-			$content .= "\n\t<!-- Took " . (microtime(true) - $slimdown_start) . " seconds to parse markdown -->\n";
+			$content .= "\n\t\t<!-- Took " . (microtime(true) - $parsing_start) . " seconds to parse page source -->\n";
 			
 			if(isset($_GET["printable"]) and $_GET["printable"] === "yes")
 				exit(page_renderer::render_minimal($title, $content));
@@ -1247,6 +1147,134 @@ register_module([
 
 
 
+
+register_module([
+	"name" => "Deault Parser",
+	"version" => "0.7",
+	"author" => "Johnny Broadway & Starbeamrainbowlabs",
+	"description" => "The default parser for Pepperminty Wiki. Based on Johnny Broadway's Slimdown (with more than a few modifications). This parser's features are documented in the help page.",
+	"id" => "parser-default",
+	"code" => function() {
+		add_parser(function($markdown) {
+			return Slimdown::render($markdown);
+		});
+	}
+]);
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// Slimdown /////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////// %slimdown% //
+////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Slimdown - A very basic regex-based Markdown parser. Supports the
+ * following elements (and can be extended via Slimdown::add_rule()):
+ *
+ * - Headers
+ * - Links
+ * - Bold
+ * - Emphasis
+ * - Deletions
+ * - Quotes
+ * - Inline code
+ * - Blockquotes
+ * - Ordered/unordered lists
+ * - Horizontal rules
+ *
+ * Author: Johnny Broadway <johnny@johnnybroadway.com>
+ * Website: https://gist.github.com/jbroadway/2836900
+ * License: MIT
+ */
+
+/**
+ * Modified by Starbeamrainbowlabs (starbeamrainbowlabs)
+ * 
+ 	* Changed bold to use single asterisks
+ 	* Changed italics to use single underscores
+ 	* Added one to add the heading levels (no <h1> tags allowed)
+ 	* Added wiki style internal link parsing
+ 	* Added wiki style internal link parsing with display text
+ 	* Added image support
+ */
+class Slimdown {
+	public static $rules = array (
+		'/\r\n/' => "\n",											// new line normalisation
+		'/(#+)(.*)/' => 'self::header',								// headers
+		'/(\*)(.*?)\1/' => '<strong>\2</strong>',					// bold
+		'/(_)(.*?)\1/' => '<em>\2</em>',							// emphasis
+		
+		// todo test these
+		'/!\[(.*)\]\(([^\s]+)\s(\d+.+)\s(left|right)\)/' => '<img src="\2" alt="\1" style="max-width: \3; float: \4;" />',		// images with size
+		'/!\[(.*)\]\(([^\s]+)\s(\d+.+)\)/' => '<img src="\2" alt="\1" style="max-width: \3;" />',		// images with size
+		'/!\[(.*)\]\((.*)\)/' => '<img src="\2" alt="\1" />',		// basic images
+		// todo end
+		
+		'/\[\[([a-zA-Z0-9\_\- ]+)\|([a-zA-Z0-9\_\- ]+)\]\]/' => '<a href=\'index.php?page=\1\'>\2</a>',	//internal links with display text
+		'/\[\[([a-zA-Z0-9\_\- ]+)\]\]/' => '<a href=\'index.php?page=\1\'>\1</a>',	//internal links
+		'/\[([^\[]+)\]\(([^\)]+)\)/' => '<a href=\'\2\' target=\'_blank\'>\1</a>',	// links
+		'/\~\~(.*?)\~\~/' => '<del>\1</del>',						// del
+		'/\:\"(.*?)\"\:/' => '<q>\1</q>',							// quote
+		'/`(.*?)`/' => '<code>\1</code>',							// inline code
+		'/\n\s*(\*|-)(.*)/' => 'self::ul_list',						// ul lists
+		'/\n[0-9]+\.(.*)/' => 'self::ol_list',						// ol lists
+		'/\n(&gt;|\>)(.*)/' => 'self::blockquote',					// blockquotes
+		'/\n-{3,}/' => "\n<hr />",									// horizontal rule
+		'/\n([^\n]+)\n\n/' => 'self::para',							// add paragraphs
+		'/<\/ul>\s?<ul>/' => '',									// fix extra ul
+		'/<\/ol>\s?<ol>/' => '',									// fix extra ol
+		'/<\/blockquote><blockquote>/' => "\n"						// fix extra blockquote
+	);
+	private static function para ($regs) {
+		$line = $regs[1];
+		$trimmed = trim ($line);
+		if (preg_match ('/^<\/?(ul|ol|li|h|p|bl)/', $trimmed)) {
+			return "\n" . $line . "\n";
+		}
+		return sprintf ("\n<p>%s</p>\n", $trimmed);
+	}
+	private static function ul_list ($regs) {
+		$item = $regs[2];
+		return sprintf ("\n<ul>\n\t<li>%s</li>\n</ul>", trim($item));
+	}
+	private static function ol_list ($regs) {
+		$item = $regs[1];
+		return sprintf ("\n<ol>\n\t<li>%s</li>\n</ol>", trim($item));
+	}
+	private static function blockquote ($regs) {
+		$item = $regs[2];
+		return sprintf ("\n<blockquote>%s</blockquote>", trim($item));
+	}
+	private static function header ($regs) {
+		list ($tmp, $chars, $header) = $regs;
+		$level = strlen ($chars);
+		return sprintf ('<h%d>%s</h%d>', $level + 1, trim($header), $level + 1);
+	}
+	
+	/**
+	 * Add a rule.
+	 */
+	public static function add_rule ($regex, $replacement) {
+		self::$rules[$regex] = $replacement;
+	}
+	/**
+	 * Render some Markdown into HTML.
+	 */
+	public static function render ($text) {
+		foreach (self::$rules as $regex => $replacement) {
+			if (is_callable ( $replacement)) {
+				$text = preg_replace_callback ($regex, $replacement, $text);
+			} else {
+				$text = preg_replace ($regex, $replacement, $text);
+			}
+		}
+		return trim ($text);
+	}
+}
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
 // %next_module% //
 
 
diff --git a/module_index.json b/module_index.json
index 1e5a25d..673dc4d 100644
--- a/module_index.json
+++ b/module_index.json
@@ -81,10 +81,18 @@
     },
     {
         "name": "Page viewer",
-        "version": "0.6",
+        "version": "0.7",
         "author": "Starbeamrainbowlabs",
         "description": "Allows you to view pages. You should include this one.",
         "id": "page-view",
-        "lastupdate": 1432497918
+        "lastupdate": 1432719098
+    },
+    {
+        "name": "Deault Parser",
+        "version": "0.7",
+        "author": "Johnny Broadway & Starbeamrainbowlabs",
+        "description": "The default parser for Pepperminty Wiki. Based on Johnny Broadway's Slimdown (with more than a few modifications). This parser's features are documented in the help page.",
+        "id": "parser-default",
+        "lastupdate": 1432718472
     }
 ]
\ No newline at end of file
diff --git a/modules/page-view.php b/modules/page-view.php
index 8a4f221..a060bf9 100644
--- a/modules/page-view.php
+++ b/modules/page-view.php
@@ -1,13 +1,13 @@
 <?php
 register_module([
 	"name" => "Page viewer",
-	"version" => "0.6",
+	"version" => "0.7",
 	"author" => "Starbeamrainbowlabs",
 	"description" => "Allows you to view pages. You should include this one.",
 	"id" => "page-view",
 	"code" => function() {
 		add_action("view", function() {
-			global $pageindex, $settings, $page;
+			global $pageindex, $settings, $page, $parse_page_source;
 			
 			//check to make sure that the page exists
 			if(!isset($pageindex->$page))
@@ -30,11 +30,11 @@ register_module([
 			$title = "$page - $settings->sitename";
 			$content = "<h1>$page</h1>";
 			
-			$slimdown_start = microtime(true);
+			$parsing_start = microtime(true);
 			
-			$content .= Slimdown::render(file_get_contents("$page.md"));
+			$content .= $parse_page_source(file_get_contents("$page.md"));
 			
-			$content .= "\n\t<!-- Took " . (microtime(true) - $slimdown_start) . " seconds to parse markdown -->\n";
+			$content .= "\n\t\t<!-- Took " . (microtime(true) - $parsing_start) . " seconds to parse page source -->\n";
 			
 			if(isset($_GET["printable"]) and $_GET["printable"] === "yes")
 				exit(page_renderer::render_minimal($title, $content));
diff --git a/modules/parser-default.php b/modules/parser-default.php
new file mode 100644
index 0000000..f05b99c
--- /dev/null
+++ b/modules/parser-default.php
@@ -0,0 +1,127 @@
+<?php
+register_module([
+	"name" => "Deault Parser",
+	"version" => "0.7",
+	"author" => "Johnny Broadway & Starbeamrainbowlabs",
+	"description" => "The default parser for Pepperminty Wiki. Based on Johnny Broadway's Slimdown (with more than a few modifications). This parser's features are documented in the help page.",
+	"id" => "parser-default",
+	"code" => function() {
+		add_parser(function($markdown) {
+			return Slimdown::render($markdown);
+		});
+	}
+]);
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// Slimdown /////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////// %slimdown% //
+////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Slimdown - A very basic regex-based Markdown parser. Supports the
+ * following elements (and can be extended via Slimdown::add_rule()):
+ *
+ * - Headers
+ * - Links
+ * - Bold
+ * - Emphasis
+ * - Deletions
+ * - Quotes
+ * - Inline code
+ * - Blockquotes
+ * - Ordered/unordered lists
+ * - Horizontal rules
+ *
+ * Author: Johnny Broadway <johnny@johnnybroadway.com>
+ * Website: https://gist.github.com/jbroadway/2836900
+ * License: MIT
+ */
+
+/**
+ * Modified by Starbeamrainbowlabs (starbeamrainbowlabs)
+ * 
+ 	* Changed bold to use single asterisks
+ 	* Changed italics to use single underscores
+ 	* Added one to add the heading levels (no <h1> tags allowed)
+ 	* Added wiki style internal link parsing
+ 	* Added wiki style internal link parsing with display text
+ 	* Added image support
+ */
+class Slimdown {
+	public static $rules = array (
+		'/\r\n/' => "\n",											// new line normalisation
+		'/(#+)(.*)/' => 'self::header',								// headers
+		'/(\*)(.*?)\1/' => '<strong>\2</strong>',					// bold
+		'/(_)(.*?)\1/' => '<em>\2</em>',							// emphasis
+		
+		// todo test these
+		'/!\[(.*)\]\(([^\s]+)\s(\d+.+)\s(left|right)\)/' => '<img src="\2" alt="\1" style="max-width: \3; float: \4;" />',		// images with size
+		'/!\[(.*)\]\(([^\s]+)\s(\d+.+)\)/' => '<img src="\2" alt="\1" style="max-width: \3;" />',		// images with size
+		'/!\[(.*)\]\((.*)\)/' => '<img src="\2" alt="\1" />',		// basic images
+		// todo end
+		
+		'/\[\[([a-zA-Z0-9\_\- ]+)\|([a-zA-Z0-9\_\- ]+)\]\]/' => '<a href=\'index.php?page=\1\'>\2</a>',	//internal links with display text
+		'/\[\[([a-zA-Z0-9\_\- ]+)\]\]/' => '<a href=\'index.php?page=\1\'>\1</a>',	//internal links
+		'/\[([^\[]+)\]\(([^\)]+)\)/' => '<a href=\'\2\' target=\'_blank\'>\1</a>',	// links
+		'/\~\~(.*?)\~\~/' => '<del>\1</del>',						// del
+		'/\:\"(.*?)\"\:/' => '<q>\1</q>',							// quote
+		'/`(.*?)`/' => '<code>\1</code>',							// inline code
+		'/\n\s*(\*|-)(.*)/' => 'self::ul_list',						// ul lists
+		'/\n[0-9]+\.(.*)/' => 'self::ol_list',						// ol lists
+		'/\n(&gt;|\>)(.*)/' => 'self::blockquote',					// blockquotes
+		'/\n-{3,}/' => "\n<hr />",									// horizontal rule
+		'/\n([^\n]+)\n\n/' => 'self::para',							// add paragraphs
+		'/<\/ul>\s?<ul>/' => '',									// fix extra ul
+		'/<\/ol>\s?<ol>/' => '',									// fix extra ol
+		'/<\/blockquote><blockquote>/' => "\n"						// fix extra blockquote
+	);
+	private static function para ($regs) {
+		$line = $regs[1];
+		$trimmed = trim ($line);
+		if (preg_match ('/^<\/?(ul|ol|li|h|p|bl)/', $trimmed)) {
+			return "\n" . $line . "\n";
+		}
+		return sprintf ("\n<p>%s</p>\n", $trimmed);
+	}
+	private static function ul_list ($regs) {
+		$item = $regs[2];
+		return sprintf ("\n<ul>\n\t<li>%s</li>\n</ul>", trim($item));
+	}
+	private static function ol_list ($regs) {
+		$item = $regs[1];
+		return sprintf ("\n<ol>\n\t<li>%s</li>\n</ol>", trim($item));
+	}
+	private static function blockquote ($regs) {
+		$item = $regs[2];
+		return sprintf ("\n<blockquote>%s</blockquote>", trim($item));
+	}
+	private static function header ($regs) {
+		list ($tmp, $chars, $header) = $regs;
+		$level = strlen ($chars);
+		return sprintf ('<h%d>%s</h%d>', $level + 1, trim($header), $level + 1);
+	}
+	
+	/**
+	 * Add a rule.
+	 */
+	public static function add_rule ($regex, $replacement) {
+		self::$rules[$regex] = $replacement;
+	}
+	/**
+	 * Render some Markdown into HTML.
+	 */
+	public static function render ($text) {
+		foreach (self::$rules as $regex => $replacement) {
+			if (is_callable ( $replacement)) {
+				$text = preg_replace_callback ($regex, $replacement, $text);
+			} else {
+				$text = preg_replace ($regex, $replacement, $text);
+			}
+		}
+		return trim ($text);
+	}
+}
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+?>
