diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6289790 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +startup*.png, config-*.php \ No newline at end of file diff --git a/admin/checkadminlogin.php b/admin/checkadminlogin.php new file mode 100644 index 0000000..dc38d3f --- /dev/null +++ b/admin/checkadminlogin.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/admin/index.php b/admin/index.php new file mode 100644 index 0000000..ee66465 --- /dev/null +++ b/admin/index.php @@ -0,0 +1,148 @@ +http://$3$4'", $txt); + +$txt = Parsedown::instance()->parse($txt); + +if (isset($_FILES["file"])) { +$allok = 0; + +$uploadLocation = "../" . UPLOAD_LOCATION . ""; +$config['max_size'] = "100000000"; + +$target_path = $uploadLocation; +$extrl = " "; +$seperator = "-"; +// $rndno=rand(); +$rndno = substr(md5_file($_FILES['file']['tmp_name']), 0, 7); +if (move_uploaded_file($_FILES['file']['tmp_name'], $target_path.$rndno.$seperator.$_FILES["file"]["name"])) { //.$_FILES["file"]["name"] +$fileurl = UPLOAD_LOCATION.$rndno.$seperator.$_FILES['file']['name']; +$filephp = "image.php?url=".$rndno.$seperator.$_FILES['file']['name']; +$extrl = '

'; +} +else{ +die("File upload error"); +} + +} + +if (isset($_POST["txt"]) && isset($_POST["tim"])) { + +include "../connect.php"; + +$mysql_table = MYSQL_TABLE; +$qry = "INSERT INTO `$mysql_table` (`id`, `txt`, `tim`) VALUES (NULL, '".mysql_escape_string(nl2br($txt.$extrl))."', '".mysql_escape_string($tim)."')"; +$result = mysql_query($qry); + +if (!$result) { + die("Error! ".mysql_error()); +} else { + $allok = 1; +} +mysql_close($link); + +} +?> + + + + + Create post + + + + + + + +
 
+

Create postSent'; +} +else { +echo ' Error'; +} +?>

+
+ +
+ + +
+ + + + diff --git a/admin/login.php b/admin/login.php new file mode 100644 index 0000000..efaa439 --- /dev/null +++ b/admin/login.php @@ -0,0 +1,44 @@ + + + + + + Please login to admin + + + +
 
+

Please login to admin

+
+
+ +
+ + + + + $_POST["un"], 'password' => $shaedpass); + setcookie("adminlogin", json_encode($arr), time()+86400); + header("Location: index.php"); +} +?> \ No newline at end of file diff --git a/checklogin.php b/checklogin.php new file mode 100644 index 0000000..fa05e6b --- /dev/null +++ b/checklogin.php @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/config-sample.php b/config-sample.php new file mode 100644 index 0000000..423acfc --- /dev/null +++ b/config-sample.php @@ -0,0 +1,31 @@ +github + '); +define('MBLOG_DESC', ' +

+ BLOG DESCRIPTION +

'); + + +define('MBLOG_PULLEY_TEXT', "What's this?"); +define('MBLOG_TOOLTIPS_TEXT', "Tap post to comment and like. :)"); +?> \ No newline at end of file diff --git a/connect.php b/connect.php new file mode 100644 index 0000000..88f7405 --- /dev/null +++ b/connect.php @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/css/LondrinaSolid.ttf b/css/LondrinaSolid.ttf new file mode 100755 index 0000000..6da0bb1 Binary files /dev/null and b/css/LondrinaSolid.ttf differ diff --git a/css/NOTICE.md b/css/NOTICE.md new file mode 100644 index 0000000..5b5b36e --- /dev/null +++ b/css/NOTICE.md @@ -0,0 +1 @@ +back.png is refrenced in script in index.php line 180. \ No newline at end of file diff --git a/css/back.png b/css/back.png new file mode 100644 index 0000000..558e543 Binary files /dev/null and b/css/back.png differ diff --git a/css/bg.gif b/css/bg.gif new file mode 100644 index 0000000..9f1b8b5 Binary files /dev/null and b/css/bg.gif differ diff --git a/css/likebtnstyles.css b/css/likebtnstyles.css new file mode 100644 index 0000000..9989063 --- /dev/null +++ b/css/likebtnstyles.css @@ -0,0 +1,47 @@ +@import url(http://fonts.googleapis.com/css?family=Londrina+Solid); +* { +padding: 0; +margin: 0; +} +body, html { +width: 100%; +background-size: 100px 100px; +font-family: "Londrina Solid"; +font-size: 12px; +text-align: right; +} +.btn, .btnm { +letter-spacing:1px; +font-family: "Londrina Solid"; +background-color: rgba(0, 0, 0, 0.5) ; +border-radius: 5px; +-webkit-border-radius: 5px; +-moz-border-radius: 5px; +-o-border-radius: 5px; +-ms-border-radius: 5px; +border: 0; +padding: 5px 8px; +color: #eee; +margin: 1px; +font-size: 12px; +-webkit-appearance: none; +} +.btn:hover { +background-color: rgba(0, 0, 0, 0.6); +} +.btn:active { +background-color: rgba(0, 0, 0, 0.7); +} +.btnm { +display: inline-block; +border-bottom-left-radius: 20px; +border-top-left-radius: 20px; +-webkit-border-bottom-left-radius: 20px; +-webkit-border-top-left-radius: 20px; +-moz-border-bottom-left-radius: 20px; +-moz-border-top-left-radius: 20px; +-o-border-bottom-left-radius: 20px; +-o-border-top-left-radius: 20px; +-ms-border-bottom-left-radius: 20px; +-ms-border-top-left-radius: 20px; +} \ No newline at end of file diff --git a/css/startupPhone320.png b/css/startupPhone320.png new file mode 100644 index 0000000..a449ad8 Binary files /dev/null and b/css/startupPhone320.png differ diff --git a/css/startupPhone640.png b/css/startupPhone640.png new file mode 100644 index 0000000..b1e2c7e Binary files /dev/null and b/css/startupPhone640.png differ diff --git a/css/styles.css b/css/styles.css new file mode 100644 index 0000000..980eec9 --- /dev/null +++ b/css/styles.css @@ -0,0 +1,372 @@ +@import url(http://fonts.googleapis.com/css?family=Londrina+Solid); +* { +padding: 0; +margin: 0; +-webkit-tap-highlight-color: rgba(50, 205, 102, 0.65); +} +body, html { +width: 100%; +background: #aaa url(bg.gif) repeat center center; +background-size: 100px 100px; +font-family: "Londrina Solid", Helvitica; +font-size: 17px; +color: #444; +font-weight: 300; +height: 100%; +text-align: center; +overflow: hidden; +} +::-moz-selection { +background-color: rgba(50, 205, 102, 0.65); +} +::selection { +background-color: rgba(50, 205, 102, 0.65); +} +ul, ol { +padding: 0; +margin: 0; +padding-left: 20px; +} +li { +padding: 0; +margin: 0; +} +a { +color: inherit; +text-decoration: none; +} +#mbinfo a { +color: #ddf; +text-decoration: none; +} +#mbinfo a:hover { +color: #cce; +text-decoration: underline; +} +#mbinfo a:active { +color: #bbd; +text-decoration: underline; +} +h1 { +font-weight: 300; +padding: 5px 20px 0px 20px; +font-size: 30px; +color: #eee; +} +h2 { +font-weight: 300; +padding: 10px 20px 0px 20px; +font-size: 23px; +color: #eee; +} +div#bio { +padding: 0px 10px 0px 10px; +text-align: center; +width: 100%; +} +div#mbinfo { +width: 100%; +background-color: rgba(0, 0, 0, 0.5) ; +color: #ddd; +padding-bottom: 2px; +overflow: hidden; +transition-duration: 1s; +-moz-transition-duration: 1s; +-webkit-transition-duration: 1s; +-o-transition-duration: 1s; +transition-property: height; +-moz-transition-property: height; +-webkit-transition-property: height; +-o-transition-property: height; +height: 1px; +} +div#pulley { +background-color: rgba(0, 0, 0, 0.5) ; +border-bottom-right-radius: 5px; +border-bottom-left-radius: 5px; +-webkit-border-bottom-right-radius: 5px; +-webkit-border-bottom-left-radius: 5px; +-moz-border-bottom-right-radius: 5px; +-moz-border-bottom-left-radius: 5px; +-o-border-bottom-right-radius: 5px; +-o-border-bottom-left-radius: 5px; +-ms-border-bottom-right-radius: 5px; +-ms-border-bottom-left-radius: 5px; +text-align: center; +color: #ddd; +width: 150px; +padding: 5px; +margin-right: 5px; +margin-left: auto; +} + +#scrollable { +overflow-y: scroll; +overflow-scrolling: touch; +-webkit-overflow-scrolling: touch; +-moz-overflow-scrolling: touch; +-o-overflow-scrolling: touch; +-ms-overflow-scrolling: touch; +position: relative; +height: 100%; +background: #fff; +background: #aaa url(bg.gif) repeat center center; +background-size: 100px 100px; +} +#content { +min-height: 100%; +transform: translateZ(0); +-webkit-transform: translateZ(0); +-moz-transform: translateZ(0); +-o-transform: translateZ(0); +-ms-transform: translateZ(0); +max-width: 720px; +text-align: left; +margin: 0 auto; +text-align: left; +} +#floating { +width: 100%; +position: absolute; +top: 0px; +z-index: 10; +} +.posts { +border-radius: 10px; +-webkit-border-radius: 10px; +-moz-border-radius: 10px; +-o-border-radius: 10px; +-ms-border-radius: 10px; +margin: 20px; +box-shadow: 0 0 5px rgba(0, 0, 0, 0.6); +transition: all 1s; +-webkit-transition: all 1s; +-moz-transition: all 1s; +-o-transition: all 1s; +-ms-transition: all 1s; +display: block; +} +.post { +padding: 10px 10px 11px 10px; +border: 1px solid #333; +border-bottom: none; +background-color: rgba(0, 0, 0, 0.075); +display: block; +width: auto; +transition: 1s background-color; +-webkit-transition: 1s background-color; +-moz-transition: 1s background-color; +-o-transition: 1s background-color; +-ms-transition: 1s background-color; +} +.post:first-child { +border-top-right-radius: 10px; +border-top-left-radius: 10px; +-webkit-top-bottom-right-radius: 10px; +-webkit-top-bottom-left-radius: 10px; +-moz-top-bottom-right-radius: 10px; +-moz-top-bottom-left-radius: 10px; +-o-top-bottom-right-radius: 10px; +-o-top-bottom-left-radius: 10px; +-ms-top-bottom-right-radius: 10px; +-ms-top-bottom-left-radius: 10px; +} +.post:last-child { +border-bottom-right-radius: 10px; +border-bottom-left-radius: 10px; +-webkit-border-bottom-right-radius: 10px; +-webkit-border-bottom-left-radius: 10px; +-moz-border-bottom-right-radius: 10px; +-moz-border-bottom-left-radius: 10px; +-o-border-bottom-right-radius: 10px; +-o-border-bottom-left-radius: 10px; +-ms-border-bottom-right-radius: 10px; +-ms-border-bottom-left-radius: 10px; +border-bottom: 1px solid #333; +} +.post:hover:not(.detail) { +background-color: rgba(0, 0, 0, 0.125); +transition: 1s background-color; +-webkit-transition: 1s background-color; +-moz-transition: 1s background-color; +-o-transition: 1s background-color; +-ms-transition: 1s background-color; +} +.post:active:not(.detail) { +background-color: rgba(0, 0, 0, 0.135); +transition: none; +-webkit-transition: none; +-moz-transition: none; +-o-transition: none; +-ms-transition: none; +} +#spacing { +height: 40px; +width: 100%; +} +.t { +padding: 4px 4px 6px 4px; +display: block; +width: auto; +word-wrap: break-word; +} +.i{ +font-size: 10px; +text-align: right; +} +.tp { +font-size: 22px; +min-height: 50px; +} +.tp a:link { +color: #226; +text-decoration: none; +} +.tp a:hover { +color: #337; +text-decoration: underline; +} +.tp a:active { +color: #448; +text-decoration: underline; +} +.ip { +font-size: 15px; +} +hr.bfo { +border: none; +height: 1px; +background-color: #333; +margin: 10px 10px 7px 10px; +box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.6); +} +hr.aft { +border: none; +height: 1px; +background-color: #333; +margin: 0px 10px 20px 10px; +box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.6); +} +.toptips { +height: auto; +margin: 3px 30px 3px 30px; +padding: 5px; +} +#topbar { +display: block; +} +.backbutton { +height: auto; +padding: 5px 0px 0px 20px; +margin: 0px 30px -6px 30px; +} +.backbutton:hover { +transition: 1s background-color; +-webkit-transition: 1s background-color; +-moz-transition: 1s background-color; +-o-transition: 1s background-color; +-ms-transition: 1s background-color; +background-color: rgba(50, 205, 102, 0.65); +} +.backbutton:active { +transition: 1s background-color; +-webkit-transition: 1s background-color; +-moz-transition: 1s background-color; +-o-transition: 1s background-color; +-ms-transition: 1s background-color; +background-color: rgba(25, 100, 50, 0.70); +} +iframe.like { + height: 30px; + width: 100%; + border: none; +} +.iframeh { + width: auto; + margin: 0px 10px 0px 10px; +} +@keyframes loading { +from { +-webkit-transform: rotate(0deg); +} +to { +-webkit-transform: rotate(360deg); +} +} +@-moz-keyframes loading { +from { +transform: rotate(0deg); +} +to { +transform: rotate(360deg); +} +} +@-webkit-keyframes loading { +from { +-webkit-transform: rotate(0deg); +} +to { +-webkit-transform: rotate(360deg); +} +} +@-o-keyframes loading { +from { +transform: rotate(0deg); +} +to { +transform: rotate(360deg); +} +} +.loadingh { + text-align: right; +} +.loading { + width: 20px; + height: 20px; + background-color: rgba(0, 0, 0, 0.5); + border-radius: 10px; + border-top-right-radius: 0px; + -webkit-border-radius: 10px; + -webkit-border-top-right-radius: 0px; + -moz-border-radius: 10px; + -moz-border-top-right-radius: 0px; + -o-border-radius: 10px; + -o-border-top-right-radius: 0px; + -ms-border-radius: 10px; + -ms-border-top-right-radius: 0px; + animation: loading 1s infinite; + -webkit-animation: loading 1s infinite; + -moz-animation: loading 1s infinite; + -o-animation: loading 1s infinite; + -ms-animation: loading 1s infinite; + display: inline-block; + margin-right: 5px; +} +.statusbarpadd { + display: none; + height: 20px; + width: 100%; +} +#list img.pim { + width: 150px; +} +#det img.pim { + width: 90%; +} +#det { +display: block; +} +#disqus_thread { + padding: 10px 10px 0px 10px; +} + +@media all and (min-width: 750px) { +div#pulley { + margin-right: 100px; +} +} +@media all and (min-width: 950px) { +div#pulley { + margin-right: 200px; +} +} \ No newline at end of file diff --git a/css/tinystyles.css b/css/tinystyles.css new file mode 100644 index 0000000..2a03158 --- /dev/null +++ b/css/tinystyles.css @@ -0,0 +1,141 @@ +@import url(http://fonts.googleapis.com/css?family=Londrina+Solid); +* { +padding: 0; +margin: 0; +} +body, html { +width: 100%; +background: #aaa url(bg.gif) repeat top left; +background-size: 100px 100px; +font-family: "Londrina Solid"; +font-size: 17px; +text-align: center; +} + +form.login { +text-align: left; +width: 250px; +margin: 10px auto 0 -100px; +position: relative; +left: 50%; +} + +h1 { +font-weight: 300; +padding: 5px 20px 0px 20px; +font-size: 30px; +color: #444; +} +input, textarea { +letter-spacing:1px; +font-family: "Londrina Solid"; +background-color: rgba(0, 0, 0, 0.5) ; +border-radius: 5px; +-webkit-border-radius: 5px; +-moz-border-radius: 5px; +-o-border-radius: 5px; +-ms-border-radius: 5px; +border: 0; +padding: 10px; +color: #eee; +margin: 3px 5px 3px 5px; +font-size: 17px; +font-width: 15px; +} +textarea { + width: 90%; + height: 200px; +} +input:focus, textarea:focus { +background-color: rgba(0, 0, 0, 0.6); +} +form { +text-align: center; +width: 100%; +} +#time { + width: 170px; + font-size: 12px; + padding-top: 13px; + padding-bottom: 13px; +} +input[type=submit], input[type=file] { + width: 33%; + -webkit-appearance: none; + -moz-appearance: none; + -o-appearance: none; + -ms-appearance: none; +} +input[type=submit]:hover { +background-color: rgba(0, 0, 0, 0.6); +} +input[type=submit]:active { +background-color: rgba(0, 0, 0, 0.7); +} +input[type=file] { +width: 90%; +padding: 2px 5px; +} +.red { + color: #f00; + font-size: 10px; +} +.statusbarpadd { + display: none; + height: 20px; + width: 100%; +} +@keyframes loading { +from { +-webkit-transform: rotate(0deg); +} +to { +-webkit-transform: rotate(360deg); +} +} +@-moz-keyframes loading { +from { +transform: rotate(0deg); +} +to { +transform: rotate(360deg); +} +} +@-webkit-keyframes loading { +from { +-webkit-transform: rotate(0deg); +} +to { +-webkit-transform: rotate(360deg); +} +} +@-o-keyframes loading { +from { +transform: rotate(0deg); +} +to { +transform: rotate(360deg); +} +} +.loading { + width: 20px; + height: 20px; + background-color: rgba(0, 0, 0, 0.5); + border-radius: 10px; + border-top-right-radius: 0px; + -webkit-border-radius: 10px; + -webkit-border-top-right-radius: 0px; + -moz-border-radius: 10px; + -moz-border-top-right-radius: 0px; + -o-border-radius: 10px; + -o-border-top-right-radius: 0px; + -ms-border-radius: 10px; + -ms-border-top-right-radius: 0px; + animation: loading 1s infinite; + -webkit-animation: loading 1s infinite; + -moz-animation: loading 1s infinite; + -o-animation: loading 1s infinite; + -ms-animation: loading 1s infinite; + display: inline-block; + margin-right: 5px; +} \ No newline at end of file diff --git a/detail.php b/detail.php new file mode 100644 index 0000000..3580956 --- /dev/null +++ b/detail.php @@ -0,0 +1,33 @@ + +
+ http://$3$4'", stripslashes($row["txt"])); + // echo $postlinked; + echo stripslashes($row["txt"]); + ?> +
+
+ at +
+
+
+
+ \ No newline at end of file diff --git a/get.php b/get.php new file mode 100644 index 0000000..5c873d3 --- /dev/null +++ b/get.php @@ -0,0 +1,19 @@ +stripslashes($row["txt"]), "tim"=>$row["tim"], "id"=>$row["id"])); +} +echo json_encode(array("posts"=>$jspo, "lastid"=>$newlastid)); + +mysql_close($link); +?> \ No newline at end of file diff --git a/image.php b/image.php new file mode 100644 index 0000000..71fb929 --- /dev/null +++ b/image.php @@ -0,0 +1,89 @@ + \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..15be362 --- /dev/null +++ b/index.php @@ -0,0 +1,224 @@ + + + + + + +<?php echo MBLOG_TITLE; ?> + + + + + + + + + + +
+
 
+
+

+

+
+ +
+
+
+
+ +
+
+
 
+
 
+
+
+
'.$postlinked.'
'.$row["tim"].'
'; + if ($iffirst==0) { + $newlastid=$row["id"]+1; + $iffirst=1; + } + } + mysql_close($link); + ?> +
+
+
+
+ +
+
+ + + comments powered by Disqus + +
+
+
 
+
+
+ + + + + + + + \ No newline at end of file diff --git a/like.php b/like.php new file mode 100644 index 0000000..d301aeb --- /dev/null +++ b/like.php @@ -0,0 +1,49 @@ + + + + +Like + + + + +
+" /> + +
+ + \ No newline at end of file diff --git a/login.php b/login.php new file mode 100644 index 0000000..6fd9cca --- /dev/null +++ b/login.php @@ -0,0 +1,44 @@ + + + + + + Please login + + + +
 
+

Please login

+
+
+ +
+ + + + + $_POST["un"], 'password' => $shaedpass); + setcookie("viewerlogin", json_encode($arr), time()+86400); + header("Location: index.php"); +} +?> \ No newline at end of file diff --git a/plugins/add2home.css b/plugins/add2home.css new file mode 100644 index 0000000..92c45ae --- /dev/null +++ b/plugins/add2home.css @@ -0,0 +1,158 @@ +/** + * + * Main container + * + */ +#addToHomeScreen { + z-index:9999; + -webkit-user-select:none; + -webkit-box-sizing:border-box; + width:240px; + font-size:15px; + padding:12px 14px; + text-align:left; + font-family:helvetica; + background-image:-webkit-gradient(linear,0 0,0 100%,color-stop(0,#fff),color-stop(0.02,#eee),color-stop(0.98,#ccc),color-stop(1,#a3a3a3)); + border:1px solid #505050; + -webkit-border-radius:8px; + -webkit-background-clip:padding-box; + color:#333; + text-shadow:0 1px 0 rgba(255,255,255,0.75); + line-height:130%; + -webkit-box-shadow:0 0 4px rgba(0,0,0,0.5); +} + +#addToHomeScreen.addToHomeIpad { + width:268px; + font-size:18px; + padding:14px; +} + +/** + * + * The 'wide' class is added when the popup contains the touch icon + * + */ +#addToHomeScreen.addToHomeWide { + width:296px; +} + +#addToHomeScreen.addToHomeIpad.addToHomeWide { + width:320px; + font-size:18px; + padding:14px; +} + +/** + * + * The balloon arrow + * + */ +#addToHomeScreen .addToHomeArrow { + position:absolute; + background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(204,204,204,0)),color-stop(0.4,rgba(204,204,204,0)),color-stop(0.4,#ccc)); + border-width:0 1px 1px 0; + border-style:solid; + border-color:#505050; + width:16px; height:16px; + -webkit-transform:rotateZ(45deg); + bottom:-9px; left:50%; + margin-left:-8px; + -webkit-box-shadow:inset -1px -1px 0 #a9a9a9; + -webkit-border-bottom-right-radius:2px; +} + + +/** + * + * The balloon arrow for iPad + * + */ +#addToHomeScreen.addToHomeIpad .addToHomeArrow { + -webkit-transform:rotateZ(-135deg); + background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(238,238,238,0)),color-stop(0.4,rgba(238,238,238,0)),color-stop(0.4,#eee)); + -webkit-box-shadow:inset -1px -1px 0 #fff; + top:-9px; bottom:auto; left:50%; +} + + +/** + * + * Close button + * + */ +#addToHomeScreen .addToHomeClose { + -webkit-box-sizing:border-box; + position:absolute; + right:4px; + top:4px; + width:18px; + height:18px; line-height:14px; + text-align:center; + text-indent:1px; + -webkit-border-radius:9px; + background:rgba(0,0,0,0.12); + color:#707070; + -webkit-box-shadow:0 1px 0 #fff; + font-size:16px; +} + + +/** + * + * The '+' icon, displayed only on iOS < 4.2 + * + */ +#addToHomeScreen .addToHomePlus { + font-weight:bold; + font-size:1.3em; +} + + +/** + * + * The 'share' icon, displayed only on iOS >= 4.2 + * + */ +#addToHomeScreen .addToHomeShare { + display:inline-block; + width:18px; + height:15px; + background-repeat:no-repeat; + background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAPCAQAAABDj1eZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUdJREFUKFNtkLtLw1AYxS/qJLhXVKr2ZRulUNtiqgSb3CziICI6ucTFVYcOnaQOFRwUnNTRwUWXgpP/QdHNUEQUHGxofYBTlRs83iZNjKTncOGe7/vx3QchXUWn6FL3jhfKUdCCr5zuifV5oDiHQM+c+CIhiiCSWNu08iq9oHXKLAiqrgR4UXqlOEYZt++ExEL0wW7+OW0G10muLv9gmqfe5FAWKmTMYQYiFL7PYwyLOD8lSjNh2gdnPzMII4QUBxc4OothbAF7GCBKQ0YbSWyPQsIhqvetS+y0ygGMo/KFZfviDvR4AhwgZU9dGYnA0J/6ndc15i3ouYIMcVVUcEXIoOxCeRCfwP8sXBSdjtpUv/1QW+K16kCCIUC4id9Fa0JtkluwVkSfqPL6RwfSDA0aNlx7k/bWgViB7bMS2/1vk5sdsZLN/ALSuL3tylO4RAAAAABJRU5ErkJggg==); + background-size:18px 15px; + text-indent:-9999em; + overflow:hidden; +} + + +/** + * + * The touch icon (if available) + * + */ +#addToHomeScreen .addToHomeTouchIcon { + display:block; + float:left; + -webkit-border-radius:6px; + -webkit-box-shadow:0 1px 3px rgba(0,0,0,0.5), + inset 0 0 2px rgba(255,255,255,0.9); + background-repeat:no-repeat; + width:57px; height:57px; + -webkit-background-size:57px 57px; + margin:0 12px 0 0; + border:1px solid #333; + -webkit-background-clip:padding-box; +} + + +/** + * + * The 'share' icon for retina display + * + */ +@media all and (-webkit-min-device-pixel-ratio: 2) { + #addToHomeScreen .addToHomeShare { + background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAeCAQAAADu6HTYAAADPElEQVR4Xq3TX2gcRRzA8e/M7mVv2+TSNpc/TZtrY6jUGqgaSAmEChKLrYK0YH0RFC2CSCkEfCghiKU04J8qNigq6os+iQV98MHWFwVBrQQRWs21lBw5cw3NNb1/udu72RGG5Y77IzXW77D7sAwf5scyYoL6BGXSDKFZwaGpLvIUaeoCkvX1MmsM0Ny6oRSQYOLuIS+YZOpfQdqslpUxcZrzTVAz4qPwW2O3CeIwC/RSzeY6Ow1QhUrkr+YOWfEKDkEP8Rij7CHKJmrFSDHBdwGEE5wiGChPN+PnT8VdRtEIl1d4gRj/1EVe5ZSBKGh8iqQpo/Fo5+3C/gz0MYg4zgwbqday1/Q4B8BGQ45d/Hi54lakCrU5obOcidJpu1+Lg9whjabyaOYLnrIBFFaRD+xe2ybMDWY66GmP/WA9cGfGp0CWhy0wkMN8inepFiH2rV1j0NQSNQbFLRQnS8/8YSDBBpadfv4CYDub2fmeHDNAsL1MBWUel0iA+Xik6eHcyvD3vAMSU1TGuA/YRS+dD7ovCQN43GKRFCU20Kd3V/avDVVyAZ5niTEuLA5/zBGWg9EEEhfJKN200Tat8CmRAQb9+wv7soPlHt2tQorsz1uPbr0HTY4sJwrH47zJZwABBAKLMBoQXepwgTwdHCo+fXMkQ4lrxEmQ5AaXipPqDY9V2vn09tgvTPI71EEGYxM+/uMJLJ4svpgaWGKOi/xKgmqLSUGSUd5f2vIVJ/CgBaTIUsZ7ZBsn0+NzfMOXLFCXQyTcybN6ep5ZZgUOHn7jpfUpsZshdugPGf+E5zjbyHTSRyQ8xfRPPM/s63RHeuknSoT22mjmmnAOIMkUZ6D1xSfPPAfd1WFKM3sO2CMaHx8M1NjnXKHaAGGkOW0C02WeYHUz4qMtx+w5gUDS8NckYe5lHsMYwCZEPyEEmjLDZFmAS7CDviMdxyTkMNVBKEmYLvbiQQBIBBbCQG04bGQvFWz6CfsCQLWCigILFwcfkGYBiOpbYuOizTAyYyDdCtrGaRG1LCkIgMYEFhI0WqQZoSlbGRyHKe4qOx7iv2bVQW9dp4dlM/x6kmwnWQcd/Q3FCqwTEiT5s+6D5v/pb0SSHyg7uhMWAAAAAElFTkSuQmCC); + } +} diff --git a/plugins/add2home.js b/plugins/add2home.js new file mode 100644 index 0000000..c62d27b --- /dev/null +++ b/plugins/add2home.js @@ -0,0 +1,351 @@ +/*! + * Add to Homescreen v2.0.4 ~ Copyright (c) 2012 Matteo Spinelli, http://cubiq.org + * Released under MIT license, http://cubiq.org/license + */ +var addToHome = (function (w) { + var nav = w.navigator, + isIDevice = 'platform' in nav && (/iphone|ipod|ipad/gi).test(nav.platform), + isIPad, + isRetina, + isSafari, + isStandalone, + OSVersion, + startX = 0, + startY = 0, + lastVisit = 0, + isExpired, + isSessionActive, + isReturningVisitor, + balloon, + overrideChecks, + + positionInterval, + closeTimeout, + + options = { + autostart: true, // Automatically open the balloon + returningVisitor: false, // Show the balloon to returning visitors only (setting this to true is HIGHLY RECCOMENDED) + animationIn: 'drop', // drop || bubble || fade + animationOut: 'fade', // drop || bubble || fade + startDelay: 2000, // 2 seconds from page load before the balloon appears + lifespan: 15000, // 15 seconds before it is automatically destroyed + bottomOffset: 14, // Distance of the balloon from bottom + expire: 0, // Minutes to wait before showing the popup again (0 = always displayed) + message: '', // Customize your message or force a language ('' = automatic) + touchIcon: false, // Display the touch icon + arrow: true, // Display the balloon arrow + hookOnLoad: true, // Should we hook to onload event? (really advanced usage) + iterations: 100 // Internal/debug use + }, + + intl = { + ar: 'قم بتثبيت هذا التطبيق على %device:انقر%icon ،ثم اضفه الى الشاشة الرئيسية.', + ca_es: 'Per instal·lar aquesta aplicació al vostre %device premeu %icon i llavors Afegir a pantalla d\'inici.', + cs_cz: 'Pro instalaci aplikace na Váš %device, stiskněte %icon a v nabídce Přidat na plochu.', + da_dk: 'Tilføj denne side til din %device: tryk på %icon og derefter Føj til hjemmeskærm.', + de_de: 'Installieren Sie diese App auf Ihrem %device: %icon antippen und dann Zum Home-Bildschirm.', + el_gr: 'Εγκαταστήσετε αυτήν την Εφαρμογή στήν συσκευή σας %device: %icon μετά πατάτε Προσθήκη σε Αφετηρία.', + en_us: 'Install this web app on your %device: tap %icon and then Add to Home Screen.', + es_es: 'Para instalar esta app en su %device, pulse %icon y seleccione Añadir a pantalla de inicio.', + fi_fi: 'Asenna tämä web-sovellus laitteeseesi %device: paina %icon ja sen jälkeen valitse Lisää Koti-valikkoon.', + fr_fr: 'Ajoutez cette application sur votre %device en cliquant sur %icon, puis Ajouter à l\'écran d\'accueil.', + he_il: 'התקן אפליקציה זו על ה-%device שלך: הקש %icon ואז הוסף למסך הבית.', + hr_hr: 'Instaliraj ovu aplikaciju na svoj %device: klikni na %icon i odaberi Dodaj u početni zaslon.', + hu_hu: 'Telepítse ezt a web-alkalmazást az Ön %device-jára: nyomjon a %icon-ra majd a Főképernyőhöz adás gombra.', + it_it: 'Installa questa applicazione sul tuo %device: premi su %icon e poi Aggiungi a Home.', + ja_jp: 'このウェブアプリをあなたの%deviceにインストールするには%iconをタップしてホーム画面に追加を選んでください。', + ko_kr: '%device에 웹앱을 설치하려면 %icon을 터치 후 "홈화면에 추가"를 선택하세요', + nb_no: 'Installer denne appen på din %device: trykk på %icon og deretter Legg til på Hjem-skjerm', + nl_nl: 'Installeer deze webapp op uw %device: tik %icon en dan Voeg toe aan beginscherm.', + pl_pl: 'Aby zainstalować tę aplikacje na %device: naciśnij %icon a następnie Dodaj jako ikonę.', + pt_br: 'Instale este aplicativo em seu %device: aperte %icon e selecione Adicionar à Tela Inicio.', + pt_pt: 'Para instalar esta aplicação no seu %device, prima o %icon e depois o Adicionar ao ecrã principal.', + ru_ru: 'Установите это веб-приложение на ваш %device: нажмите %icon, затем Добавить в «Домой».', + sv_se: 'Lägg till denna webbapplikation på din %device: tryck på %icon och därefter Lägg till på hemskärmen.', + th_th: 'ติดตั้งเว็บแอพฯ นี้บน %device ของคุณ: แตะ %icon และ เพิ่มที่หน้าจอโฮม', + tr_tr: '%device için bu uygulamayı kurduktan sonra %icon simgesine dokunarak Ana Ekrana Ekleyin.', + zh_cn: '您可以将此应用程式安装到您的 %device 上。请按 %icon 然后点选添加至主屏幕。', + zh_tw: '您可以將此應用程式安裝到您的 %device 上。請按 %icon 然後點選加入主畫面螢幕。' + }; + + function init () { + // Preliminary check, all further checks are performed on iDevices only + if ( !isIDevice ) return; + + var now = Date.now(), + i; + + // Merge local with global options + if ( w.addToHomeConfig ) { + for ( i in w.addToHomeConfig ) { + options[i] = w.addToHomeConfig[i]; + } + } + if ( !options.autostart ) options.hookOnLoad = false; + + isIPad = (/ipad/gi).test(nav.platform); + isRetina = w.devicePixelRatio && w.devicePixelRatio > 1; + isSafari = (/Safari/i).test(nav.appVersion) && !(/CriOS/i).test(nav.appVersion); + isStandalone = nav.standalone; + OSVersion = nav.appVersion.match(/OS (\d+_\d+)/i); + OSVersion = OSVersion[1] ? +OSVersion[1].replace('_', '.') : 0; + + lastVisit = +w.localStorage.getItem('addToHome'); + + isSessionActive = w.sessionStorage.getItem('addToHomeSession'); + isReturningVisitor = options.returningVisitor ? lastVisit && lastVisit + 28*24*60*60*1000 > now : true; + + if ( !lastVisit ) lastVisit = now; + + // If it is expired we need to reissue a new balloon + isExpired = isReturningVisitor && lastVisit <= now; + + if ( options.hookOnLoad ) w.addEventListener('load', loaded, false); + else if ( !options.hookOnLoad && options.autostart ) loaded(); + } + + function loaded () { + w.removeEventListener('load', loaded, false); + + if ( !isReturningVisitor ) w.localStorage.setItem('addToHome', Date.now()); + else if ( options.expire && isExpired ) w.localStorage.setItem('addToHome', Date.now() + options.expire * 60000); + + if ( !overrideChecks && ( !isSafari || !isExpired || isSessionActive || isStandalone || !isReturningVisitor ) ) return; + + var icons = options.touchIcon ? document.querySelectorAll('head link[rel=apple-touch-icon],head link[rel=apple-touch-icon-precomposed]') : [], + sizes, + touchIcon = '', + closeButton, + platform = nav.platform.split(' ')[0], + language = nav.language.replace('-', '_'), + i, l; + + balloon = document.createElement('div'); + balloon.id = 'addToHomeScreen'; + balloon.style.cssText += 'left:-9999px;-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0;-webkit-transform:translate3d(0,0,0);position:' + (OSVersion < 5 ? 'absolute' : 'fixed'); + + // Localize message + if ( options.message in intl ) { // You may force a language despite the user's locale + language = options.message; + options.message = ''; + } + if ( options.message === '' ) { // We look for a suitable language (defaulted to en_us) + options.message = language in intl ? intl[language] : intl['en_us']; + } + + // Search for the apple-touch-icon + if ( icons.length ) { + for ( i = 0, l = icons.length; i < l; i++ ) { + sizes = icons[i].getAttribute('sizes'); + + if ( sizes ) { + if ( isRetina && sizes == '114x114' ) { + touchIcon = icons[i].href; + break; + } + } else { + touchIcon = icons[i].href; + } + } + + touchIcon = ''; + } + + balloon.className = (isIPad ? 'addToHomeIpad' : 'addToHomeIphone') + (touchIcon ? ' addToHomeWide' : ''); + balloon.innerHTML = touchIcon + + options.message.replace('%device', platform).replace('%icon', OSVersion >= 4.2 ? '' : '+') + + (options.arrow ? '' : '') + + '\u00D7'; + + document.body.appendChild(balloon); + + // Add the close action + closeButton = balloon.querySelector('.addToHomeClose'); + if ( closeButton ) closeButton.addEventListener('click', clicked, false); + + if ( !isIPad && OSVersion >= 6 ) window.addEventListener('orientationchange', orientationCheck, false); + + setTimeout(show, options.startDelay); + } + + function show () { + var duration, + iPadXShift = 208; + + // Set the initial position + if ( isIPad ) { + if ( OSVersion < 5 ) { + startY = w.scrollY; + startX = w.scrollX; + } else if ( OSVersion < 6 ) { + iPadXShift = 160; + } + + balloon.style.top = startY + options.bottomOffset + 'px'; + balloon.style.left = startX + iPadXShift - Math.round(balloon.offsetWidth / 2) + 'px'; + + switch ( options.animationIn ) { + case 'drop': + duration = '0.6s'; + balloon.style.webkitTransform = 'translate3d(0,' + -(w.scrollY + options.bottomOffset + balloon.offsetHeight) + 'px,0)'; + break; + case 'bubble': + duration = '0.6s'; + balloon.style.opacity = '0'; + balloon.style.webkitTransform = 'translate3d(0,' + (startY + 50) + 'px,0)'; + break; + default: + duration = '1s'; + balloon.style.opacity = '0'; + } + } else { + startY = w.innerHeight + w.scrollY; + + if ( OSVersion < 5 ) { + startX = Math.round((w.innerWidth - balloon.offsetWidth) / 2) + w.scrollX; + balloon.style.left = startX + 'px'; + balloon.style.top = startY - balloon.offsetHeight - options.bottomOffset + 'px'; + } else { + balloon.style.left = '50%'; + balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - ( w.orientation%180 && OSVersion >= 6 ? 40 : 0 ) + 'px'; + balloon.style.bottom = options.bottomOffset + 'px'; + } + + switch (options.animationIn) { + case 'drop': + duration = '1s'; + balloon.style.webkitTransform = 'translate3d(0,' + -(startY + options.bottomOffset) + 'px,0)'; + break; + case 'bubble': + duration = '0.6s'; + balloon.style.webkitTransform = 'translate3d(0,' + (balloon.offsetHeight + options.bottomOffset + 50) + 'px,0)'; + break; + default: + duration = '1s'; + balloon.style.opacity = '0'; + } + } + + balloon.offsetHeight; // repaint trick + balloon.style.webkitTransitionDuration = duration; + balloon.style.opacity = '1'; + balloon.style.webkitTransform = 'translate3d(0,0,0)'; + balloon.addEventListener('webkitTransitionEnd', transitionEnd, false); + + closeTimeout = setTimeout(close, options.lifespan); + } + + function manualShow (override) { + if ( !isIDevice || balloon ) return; + + overrideChecks = override; + loaded(); + } + + function close () { + clearInterval( positionInterval ); + clearTimeout( closeTimeout ); + closeTimeout = null; + + var posY = 0, + posX = 0, + opacity = '1', + duration = '0', + closeButton = balloon.querySelector('.addToHomeClose'); + + if ( closeButton ) closeButton.removeEventListener('click', close, false); + if ( !isIPad && OSVersion >= 6 ) window.removeEventListener('orientationchange', orientationCheck, false); + + if ( OSVersion < 5 ) { + posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY; + posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth)/2) - startX; + } + + balloon.style.webkitTransitionProperty = '-webkit-transform,opacity'; + + switch ( options.animationOut ) { + case 'drop': + if ( isIPad ) { + duration = '0.4s'; + opacity = '0'; + posY = posY + 50; + } else { + duration = '0.6s'; + posY = posY + balloon.offsetHeight + options.bottomOffset + 50; + } + break; + case 'bubble': + if ( isIPad ) { + duration = '0.8s'; + posY = posY - balloon.offsetHeight - options.bottomOffset - 50; + } else { + duration = '0.4s'; + opacity = '0'; + posY = posY - 50; + } + break; + default: + duration = '0.8s'; + opacity = '0'; + } + + balloon.addEventListener('webkitTransitionEnd', transitionEnd, false); + balloon.style.opacity = opacity; + balloon.style.webkitTransitionDuration = duration; + balloon.style.webkitTransform = 'translate3d(' + posX + 'px,' + posY + 'px,0)'; + } + + + function clicked () { + w.sessionStorage.setItem('addToHomeSession', '1'); + isSessionActive = true; + close(); + } + + function transitionEnd () { + balloon.removeEventListener('webkitTransitionEnd', transitionEnd, false); + + balloon.style.webkitTransitionProperty = '-webkit-transform'; + balloon.style.webkitTransitionDuration = '0.2s'; + + // We reached the end! + if ( !closeTimeout ) { + balloon.parentNode.removeChild(balloon); + balloon = null; + return; + } + + // On iOS 4 we start checking the element position + if ( OSVersion < 5 && closeTimeout ) positionInterval = setInterval(setPosition, options.iterations); + } + + function setPosition () { + var matrix = new WebKitCSSMatrix(w.getComputedStyle(balloon, null).webkitTransform), + posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY, + posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth) / 2) - startX; + + // Screen didn't move + if ( posY == matrix.m42 && posX == matrix.m41 ) return; + + balloon.style.webkitTransform = 'translate3d(' + posX + 'px,' + posY + 'px,0)'; + } + + // Clear local and session storages (this is useful primarily in development) + function reset () { + w.localStorage.removeItem('addToHome'); + w.sessionStorage.removeItem('addToHomeSession'); + } + + function orientationCheck () { + balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - ( w.orientation%180 && OSVersion >= 6 ? 40 : 0 ) + 'px'; + } + + // Bootstrap! + init(); + + return { + show: manualShow, + close: close, + reset: reset + }; +})(window); diff --git a/plugins/parsedown/LICENSE.txt b/plugins/parsedown/LICENSE.txt new file mode 100755 index 0000000..baca86f --- /dev/null +++ b/plugins/parsedown/LICENSE.txt @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Emanuil Rusev, erusev.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/plugins/parsedown/Parsedown.php b/plugins/parsedown/Parsedown.php new file mode 100755 index 0000000..45144bf --- /dev/null +++ b/plugins/parsedown/Parsedown.php @@ -0,0 +1,785 @@ +', '\#', '\+', '\-', '\.', '\!'); + + foreach ($escape_sequences as $index => $escape_sequence) + { + if (strpos($text, $escape_sequence) !== FALSE) + { + $code = "\x1A".'\\'.$index.';'; + + $text = str_replace($escape_sequence, $code, $text); + + $this->escape_sequence_map[$code] = $escape_sequence; + } + } + } + + # ~ + + $text = preg_replace('/\n\s*\n/', "\n\n", $text); + $text = trim($text, "\n"); + + $lines = explode("\n", $text); + + $text = $this->parse_block_elements($lines); + + # decodes escape sequences + + foreach ($this->escape_sequence_map as $code => $escape_sequence) + { + $text = str_replace($code, $escape_sequence[1], $text); + } + + $text = rtrim($text, "\n"); + + return $text; + } + + # + # Private Methods + # + + private function parse_block_elements(array $lines, $context = '') + { + $elements = array(); + + $element = array( + 'type' => '', + ); + + foreach ($lines as $line) + { + # + # fenced elements + + switch ($element['type']) + { + case 'fenced_code_block': + + if ( ! isset($element['closed'])) + { + if (preg_match('/^[ ]*'.$element['fence'][0].'{3,}[ ]*$/', $line)) + { + $element['closed'] = true; + } + else + { + $element['text'] !== '' and $element['text'] .= "\n"; + + $element['text'] .= $line; + } + + continue 2; + } + + break; + + case 'markup': + + if ( ! isset($element['closed'])) + { + if (preg_match('{<'.$element['subtype'].'>$}', $line)) # opening tag + { + $element['depth']++; + } + + if (preg_match('{$}', $line)) # closing tag + { + $element['depth'] > 0 + ? $element['depth']-- + : $element['closed'] = true; + } + + $element['text'] .= "\n".$line; + + continue 2; + } + + break; + } + + # * + + if ($line === '') + { + $element['interrupted'] = true; + + continue; + } + + # + # composite elements + + switch ($element['type']) + { + case 'blockquote': + + if ( ! isset($element['interrupted'])) + { + $line = preg_replace('/^[ ]*>[ ]?/', '', $line); + + $element['lines'] []= $line; + + continue 2; + } + + break; + + case 'li': + + if (preg_match('/^([ ]{0,3})(\d+[.]|[*+-])[ ](.*)/', $line, $matches)) + { + if ($element['indentation'] !== $matches[1]) + { + $element['lines'] []= $line; + } + else + { + unset($element['last']); + + $elements []= $element; + + $element = array( + 'type' => 'li', + 'indentation' => $matches[1], + 'last' => true, + 'lines' => array( + preg_replace('/^[ ]{0,4}/', '', $matches[3]), + ), + ); + } + + continue 2; + } + + if (isset($element['interrupted'])) + { + if ($line[0] === ' ') + { + $element['lines'] []= ''; + + $line = preg_replace('/^[ ]{0,4}/', '', $line); + + $element['lines'] []= $line; + + continue 2; + } + } + else + { + $line = preg_replace('/^[ ]{0,4}/', '', $line); + + $element['lines'] []= $line; + + continue 2; + } + + break; + } + + # + # indentation sensitive types + + $deindented_line = $line; + + switch ($line[0]) + { + case ' ': + + # ~ + + $deindented_line = ltrim($line); + + if ($deindented_line === '') + { + continue 2; + } + + # code block + + if (preg_match('/^[ ]{4}(.*)/', $line, $matches)) + { + if ($element['type'] === 'code_block') + { + if (isset($element['interrupted'])) + { + $element['text'] .= "\n"; + + unset ($element['interrupted']); + } + + $element['text'] .= "\n".$matches[1]; + } + else + { + $elements []= $element; + + $element = array( + 'type' => 'code_block', + 'text' => $matches[1], + ); + } + + continue 2; + } + + break; + + case '#': + + # atx heading (#) + + if (preg_match('/^(#{1,6})[ ]*(.+?)[ ]*#*$/', $line, $matches)) + { + $elements []= $element; + + $level = strlen($matches[1]); + + $element = array( + 'type' => 'h.', + 'text' => $matches[2], + 'level' => $level, + ); + + continue 2; + } + + break; + + case '-': + + # setext heading (---) + + if ($line[0] === '-' and $element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[-]+[ ]*$/', $line)) + { + $element['type'] = 'h.'; + $element['level'] = 2; + + continue 2; + } + + break; + + case '=': + + # setext heading (===) + + if ($line[0] === '=' and $element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[=]+[ ]*$/', $line)) + { + $element['type'] = 'h.'; + $element['level'] = 1; + + continue 2; + } + + break; + } + + # + # indentation insensitive types + + switch ($deindented_line[0]) + { + case '<': + + # self-closing tag + + if (preg_match('{^<.+?/>$}', $deindented_line)) + { + $elements []= $element; + + $element = array( + 'type' => '', + 'text' => $deindented_line, + ); + + continue 2; + } + + # opening tag + + if (preg_match('{^<(\w+)(?:[ ].*?)?>}', $deindented_line, $matches)) + { + $elements []= $element; + + $element = array( + 'type' => 'markup', + 'subtype' => strtolower($matches[1]), + 'text' => $deindented_line, + 'depth' => 0, + ); + + preg_match('{\s*$}', $deindented_line) and $element['closed'] = true; + + continue 2; + } + + break; + + case '>': + + # quote + + if (preg_match('/^>[ ]?(.*)/', $deindented_line, $matches)) + { + $elements []= $element; + + $element = array( + 'type' => 'blockquote', + 'lines' => array( + $matches[1], + ), + ); + + continue 2; + } + + break; + + case '[': + + # reference + + if (preg_match('/^\[(.+?)\]:[ ]*([^ ]+)/', $deindented_line, $matches)) + { + $label = strtolower($matches[1]); + + $this->reference_map[$label] = trim($matches[2], '<>');; + + continue 2; + } + + break; + + case '`': + case '~': + + # fenced code block + + if (preg_match('/^([`]{3,}|[~]{3,})[ ]*(\S+)?[ ]*$/', $deindented_line, $matches)) + { + $elements []= $element; + + $element = array( + 'type' => 'fenced_code_block', + 'text' => '', + 'fence' => $matches[1], + ); + + isset($matches[2]) and $element['language'] = $matches[2]; + + continue 2; + } + + break; + + case '*': + case '+': + case '-': + case '_': + + # hr + + if (preg_match('/^([-*_])([ ]{0,2}\1){2,}[ ]*$/', $deindented_line)) + { + $elements []= $element; + + $element = array( + 'type' => 'hr', + ); + + continue 2; + } + + # li + + if (preg_match('/^([ ]*)[*+-][ ](.*)/', $line, $matches)) + { + $elements []= $element; + + $element = array( + 'type' => 'li', + 'ordered' => false, + 'indentation' => $matches[1], + 'last' => true, + 'lines' => array( + preg_replace('/^[ ]{0,4}/', '', $matches[2]), + ), + ); + + continue 2; + } + } + + # li + + if ($deindented_line[0] <= '9' and $deindented_line >= '0' and preg_match('/^([ ]*)\d+[.][ ](.*)/', $line, $matches)) + { + $elements []= $element; + + $element = array( + 'type' => 'li', + 'ordered' => true, + 'indentation' => $matches[1], + 'last' => true, + 'lines' => array( + preg_replace('/^[ ]{0,4}/', '', $matches[2]), + ), + ); + + continue; + } + + # paragraph + + if ($element['type'] === 'p') + { + if (isset($element['interrupted'])) + { + $elements []= $element; + + $element['text'] = $line; + + unset($element['interrupted']); + } + else + { + $element['text'] .= "\n".$line; + } + } + else + { + $elements []= $element; + + $element = array( + 'type' => 'p', + 'text' => $line, + ); + } + } + + $elements []= $element; + + unset($elements[0]); + + # + # ~ + # + + $markup = ''; + + foreach ($elements as $element) + { + switch ($element['type']) + { + case 'p': + + $text = $this->parse_span_elements($element['text']); + + $text = preg_replace('/[ ]{2}\n/', '
'."\n", $text); + + if ($context === 'li' and $markup === '') + { + if (isset($element['interrupted'])) + { + $markup .= "\n".'

'.$text.'

'."\n"; + } + else + { + $markup .= $text; + } + } + else + { + $markup .= '

'.$text.'

'."\n"; + } + + break; + + case 'blockquote': + + $text = $this->parse_block_elements($element['lines']); + + $markup .= '
'."\n".$text.'
'."\n"; + + break; + + case 'code_block': + case 'fenced_code_block': + + $text = htmlentities($element['text'], ENT_NOQUOTES); + + strpos($text, "\x1A\\") !== FALSE and $text = strtr($text, $this->escape_sequence_map); + + $markup .= '
'.$text.'
'."\n"; + + break; + + case 'h.': + + $text = $this->parse_span_elements($element['text']); + + $markup .= ''.$text.''."\n"; + + break; + + case 'hr': + + $markup .= '
'."\n"; + + break; + + case 'li': + + if (isset($element['ordered'])) # first + { + $list_type = $element['ordered'] ? 'ol' : 'ul'; + + $markup .= '<'.$list_type.'>'."\n"; + } + + if (isset($element['interrupted']) and ! isset($element['last'])) + { + $element['lines'] []= ''; + } + + $text = $this->parse_block_elements($element['lines'], 'li'); + + $markup .= '
  • '.$text.'
  • '."\n"; + + isset($element['last']) and $markup .= ''."\n"; + + break; + + default: + + $markup .= $element['text']."\n"; + } + } + + return $markup; + } + + private function parse_span_elements($text) + { + $map = array(); + + $index = 0; + + # code span + + if (strpos($text, '`') !== FALSE and preg_match_all('/`(.+?)`/', $text, $matches, PREG_SET_ORDER)) + { + foreach ($matches as $matches) + { + $element_text = $matches[1]; + $element_text = htmlentities($element_text, ENT_NOQUOTES); + + # decodes escape sequences + + $this->escape_sequence_map + and strpos($element_text, "\x1A") !== FALSE + and $element_text = strtr($element_text, $this->escape_sequence_map); + + # composes element + + $element = ''.$element_text.''; + + # encodes element + + $code = "\x1A".'$'.$index; + + $text = str_replace($matches[0], $code, $text); + + $map[$code] = $element; + + $index ++; + } + } + + # inline link or image + + if (strpos($text, '](') !== FALSE and preg_match_all('/(!?)(\[((?:[^\[\]]|(?2))*)\])\((.*?)\)/', $text, $matches, PREG_SET_ORDER)) # inline + { + foreach ($matches as $matches) + { + $url = $matches[4]; + + strpos($url, '&') !== FALSE and $url = preg_replace('/&(?!#?\w+;)/', '&', $url); + + if ($matches[1]) # image + { + $element = ''.$matches[3].''; + } + else + { + $element_text = $this->parse_span_elements($matches[3]); + + $element = ''.$element_text.''; + } + + # ~ + + $code = "\x1A".'$'.$index; + + $text = str_replace($matches[0], $code, $text); + + $map[$code] = $element; + + $index ++; + } + } + + # reference link or image + + if ($this->reference_map and strpos($text, '[') !== FALSE and preg_match_all('/(!?)\[(.+?)\](?:\n?[ ]?\[(.*?)\])?/ms', $text, $matches, PREG_SET_ORDER)) + { + foreach ($matches as $matches) + { + $link_definition = isset($matches[3]) && $matches[3] + ? $matches[3] + : $matches[2]; # implicit + + $link_definition = strtolower($link_definition); + + if (isset($this->reference_map[$link_definition])) + { + $url = $this->reference_map[$link_definition]; + + strpos($url, '&') !== FALSE and $url = preg_replace('/&(?!#?\w+;)/', '&', $url); + + if ($matches[1]) # image + { + $element = ''.$matches[2].''; + } + else # anchor + { + $element_text = $this->parse_span_elements($matches[2]); + + $element = ''.$element_text.''; + } + + # ~ + + $code = "\x1A".'$'.$index; + + $text = str_replace($matches[0], $code, $text); + + $map[$code] = $element; + + $index ++; + } + } + } + + # automatic link + + if (strpos($text, '<') !== FALSE and preg_match_all('/<((https?|ftp|dict):[^\^\s]+?)>/i', $text, $matches, PREG_SET_ORDER)) + { + foreach ($matches as $matches) + { + $url = $matches[1]; + + strpos($url, '&') !== FALSE and $url = preg_replace('/&(?!#?\w+;)/', '&', $url); + + $element = ':text'; + $element = str_replace(':text', $url, $element); + $element = str_replace(':href', $url, $element); + + # ~ + + $code = "\x1A".'$'.$index; + + $text = str_replace($matches[0], $code, $text); + + $map[$code] = $element; + + $index ++; + } + } + + # ~ + + strpos($text, '&') !== FALSE and $text = preg_replace('/&(?!#?\w+;)/', '&', $text); + strpos($text, '<') !== FALSE and $text = preg_replace('/<(?!\/?\w.*?>)/', '<', $text); + + # ~ + + if (strpos($text, '_') !== FALSE) + { + $text = preg_replace('/__(?=\S)(.+?)(?<=\S)__(?!_)/s', '$1', $text); + $text = preg_replace('/_(?=\S)(.+?)(?<=\S)_/s', '$1', $text); + } + + if (strpos($text, '*') !== FALSE) + { + $text = preg_replace('/\*\*(?=\S)(.+?)(?<=\S)\*\*(?!\*)/s', '$1', $text); + $text = preg_replace('/\*(?=\S)(.+?)(?<=\S)\*/s', '$1', $text); + } + + $text = strtr($text, $map); + + return $text; + } +} \ No newline at end of file diff --git a/sounds/alert.mp3 b/sounds/alert.mp3 new file mode 100644 index 0000000..7ccbed4 Binary files /dev/null and b/sounds/alert.mp3 differ diff --git a/sounds/alert.ogg b/sounds/alert.ogg new file mode 100644 index 0000000..55c175c Binary files /dev/null and b/sounds/alert.ogg differ diff --git a/sounds/alert.wav b/sounds/alert.wav new file mode 100644 index 0000000..1533ea8 Binary files /dev/null and b/sounds/alert.wav differ