added markdown support and a dropdown for the format selection. The

options other then markdown are plain text and source code (syntax
highlighting). Resolves #25
This commit is contained in:
El RIDO 2015-09-12 17:33:16 +02:00
parent 9dde7f034a
commit 0e53d1ee86
12 changed files with 1518 additions and 55 deletions

View File

@ -14,17 +14,18 @@ discussion = true
; preselect the discussion feature, defaults to false ; preselect the discussion feature, defaults to false
opendiscussion = false opendiscussion = false
; enable or disable syntax highlighting, defaults to true ; enable or disable the password feature, defaults to true
syntaxhighlighting = true password = true
; (optional) set a syntax highlighting theme, as found in css/prettify/
; syntaxhighlightingtheme = "sons-of-obsidian"
; preselect the burn-after-reading feature, defaults to false ; preselect the burn-after-reading feature, defaults to false
burnafterreadingselected = false burnafterreadingselected = false
; enable or disable the password feature, defaults to true ; which display mode to preselect by default, defaults to "syntaxhighlighting"
password = true ; make sure the value exists in [formatter_options]
defaultformatter = "syntaxhighlighting"
; (optional) set a syntax highlighting theme, as found in css/prettify/
; syntaxhighlightingtheme = "sons-of-obsidian"
; size limit per paste or comment in bytes, defaults to 2 Mibibytes ; size limit per paste or comment in bytes, defaults to 2 Mibibytes
sizelimit = 2097152 sizelimit = 2097152
@ -57,6 +58,12 @@ default = "1week"
1year = 31536000 1year = 31536000
never = 0 never = 0
[formatter_options]
; Set available formatters, their order and their labels
plaintext = "Plain Text"
syntaxhighlighting = "Source Code"
markdown = "Markdown"
[traffic] [traffic]
; time limit between calls from the same IP address in seconds ; time limit between calls from the same IP address in seconds
; Set this to 0 to disable rate limiting. ; Set this to 0 to disable rate limiting.

View File

@ -18,7 +18,7 @@ html {
} }
body { body {
font-family: Arial, Helvetica, sans-serif; font-family: Helvetica, Arial, sans-serif;
font-size: 0.9em; font-size: 0.9em;
margin-bottom: 15px; margin-bottom: 15px;
padding-left: 60px; padding-left: 60px;
@ -27,7 +27,7 @@ body {
a { color: #0f388f; } a { color: #0f388f; }
h1 { h1.title {
font-size: 3.5em; font-size: 3.5em;
font-weight: bold; font-weight: bold;
color: #000; color: #000;
@ -36,7 +36,7 @@ h1 {
cursor: pointer; cursor: pointer;
} }
h1:before { h1.title:before {
content: attr(title); content: attr(title);
position: absolute; position: absolute;
color: rgba(255,255,255,0.15); color: rgba(255,255,255,0.15);
@ -45,7 +45,7 @@ h1:before {
cursor: pointer; cursor: pointer;
} }
h2 { h2.title {
color: #000; color: #000;
font-size: 1em; font-size: 1em;
display: inline; display: inline;
@ -55,7 +55,7 @@ h2 {
bottom: 8px; bottom: 8px;
} }
h3 { h3.title {
color: #94a3b4; color: #94a3b4;
font-size: 0.7em; font-size: 0.7em;
display: inline; display: inline;
@ -76,15 +76,12 @@ h3 {
#aboutbox a { color: #94a3b4; } #aboutbox a { color: #94a3b4; }
#message, #cleartext, .replymessage { #message, #cleartext, #prettymessage, .replymessage {
clear: both; clear: both;
color: #000; color: #000;
background-color: #fff; background-color: #fff;
white-space: pre-wrap;
font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace;
font-size: 9pt; font-size: 9pt;
border: 1px solid #28343F; border: 1px solid #28343F;
padding: 5px;
box-sizing: border-box; box-sizing: border-box;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
@ -93,6 +90,12 @@ h3 {
width: 100%; width: 100%;
} }
#message, .replymessage {
padding: 5px;
white-space: pre-wrap;
font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace;
}
#status { #status {
clear: both; clear: both;
padding: 5px 10px; padding: 5px 10px;
@ -118,7 +121,7 @@ h3 {
#copyhint { color: #666; font-size: 0.85em; } #copyhint { color: #666; font-size: 0.85em; }
button, .button, #expiration { button, .button, #expiration, #formatter {
color: #fff; color: #fff;
background-color: #323b47; background-color: #323b47;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -177,7 +180,7 @@ button img {
top: 2px; top: 2px;
} }
#expiration, #rawtextbutton, #burnafterreadingoption, #opendisc { #expiration, #formatter, #rawtextbutton, #burnafterreadingoption, #opendisc {
background-color: #414d5a; background-color: #414d5a;
padding: 6px 8px; padding: 6px 8px;
margin: 0 5px 0 0; margin: 0 5px 0 0;
@ -185,14 +188,14 @@ button img {
bottom: 1px; /* WTF ? Why is this shifted by 1 pixel ? */ bottom: 1px; /* WTF ? Why is this shifted by 1 pixel ? */
} }
#expiration select { #expiration select, #formatter select {
color: #eee; color: #eee;
background: transparent; background: transparent;
border: none; border: none;
} }
#expiration select option { #expiration select option, #formatter select option {
color:#eee; color:#eee;
background: #414d5a; background: #414d5a;
} }
@ -201,7 +204,7 @@ button img {
padding: 1px 0 1px 0; padding: 1px 0 1px 0;
} }
#remainingtime { #remainingtime, #password {
color: #94a3b4; color: #94a3b4;
display: inline; display: inline;
font-size: 0.85em; font-size: 0.85em;
@ -278,7 +281,7 @@ input {
min-width: 200px; min-width: 200px;
} }
h4 { h4.title {
font-size: 1.2em; font-size: 1.2em;
color: #94a3b4; color: #94a3b4;
font-style: italic; font-style: italic;
@ -385,3 +388,37 @@ img.vizhash {
color: #000000; color: #000000;
font-size: 1.2em; font-size: 1.2em;
} }
#cleartext {
padding: 10px;
}
#cleartext * {
margin-bottom: 10px;
}
#cleartext ol {
list-style: auto;
margin-left: 15px;
}
#cleartext ul {
list-style: disc;
margin-left: 15px;
}
#cleartext h1, #cleartext h2, #cleartext h3, #cleartext h4, #cleartext h5, #cleartext h6 {
font-weight: bold;
}
#cleartext h1 {
font-size: 2em;
}
#cleartext h2 {
font-size: 1.5em;
}
#cleartext h3 {
font-size: 1.2em;
}

View File

@ -123,5 +123,9 @@
"Could not create paste: %s": "Could not create paste: %s":
"Konnte Text nicht erstellen: %s", "Konnte Text nicht erstellen: %s",
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
"Konnte Text nicht entschlüsseln: Der Schlüssel fehlt in der Adresse (Hast Du eine Umleitung oder einen URL-Verkürzer benutzt, der Teile der Adresse entfernt?)" "Konnte Text nicht entschlüsseln: Der Schlüssel fehlt in der Adresse (Hast Du eine Umleitung oder einen URL-Verkürzer benutzt, der Teile der Adresse entfernt?)",
"Format": "Format",
"Plain Text": "Nur Text",
"Source Code": "Quellcode",
"Markdown": "Markdown"
} }

View File

@ -132,5 +132,9 @@
"PiB": "Pio", "PiB": "Pio",
"EiB": "Eio", "EiB": "Eio",
"ZiB": "Zio", "ZiB": "Zio",
"YiB": "Yio" "YiB": "Yio",
"Format": "Format",
"Plain Text": "texte",
"Source Code": "code source",
"Markdown": "Markdown"
} }

View File

@ -123,5 +123,9 @@
"Could not create paste: %s": "Could not create paste: %s":
"Could not create paste: %s", "Could not create paste: %s",
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)" "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)",
"Format": "Format",
"Plain Text": "Plain Text",
"Source Code": "Source Code",
"Markdown": "Markdown"
} }

1296
js/showdown.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -183,6 +183,25 @@ $(function() {
} }
}, },
/**
* replace last child of element with message
*
* @param object element : a jQuery wrapped DOM element.
* @param string message : the message to append.
*/
setMessage: function(element, message)
{
var content = element.contents();
if (content.length > 0)
{
content[content.length - 1].nodeValue = ' ' + message;
}
else
{
this.setElementText(element, message);
}
},
/** /**
* Convert URLs to clickable links. * Convert URLs to clickable links.
* URLs to handle: * URLs to handle:
@ -513,6 +532,44 @@ $(function() {
return password; return password;
}, },
/**
* use given format on paste, defaults to plain text
*
* @param string format
*/
formatPaste: function(format)
{
switch (format || 'plaintext')
{
case 'markdown':
if (typeof Showdown == 'object')
{
var converter = new Showdown.converter();
this.clearText.html(
converter.makeHtml(this.clearText.html())
);
}
break;
case 'syntaxhighlighting':
if (typeof prettyPrint == 'function') prettyPrint();
default:
// Convert URLs to clickable links.
helper.urls2links(this.clearText);
helper.urls2links(this.prettyPrint);
}
if (format == 'markdown')
{
this.clearText.removeClass('hidden');
this.prettyMessage.addClass('hidden');
}
else
{
this.clearText.addClass('hidden');
this.prettyMessage.removeClass('hidden');
}
if (format == 'plaintext') this.prettyPrint.removeClass('prettyprint');
},
/** /**
* Show decrypted text in the display area, including discussion (if open) * Show decrypted text in the display area, including discussion (if open)
* *
@ -537,11 +594,7 @@ $(function() {
helper.setElementText(this.clearText, cleartext); helper.setElementText(this.clearText, cleartext);
helper.setElementText(this.prettyPrint, cleartext); helper.setElementText(this.prettyPrint, cleartext);
this.formatPaste(comments[0].meta.formatter);
// Convert URLs to clickable links.
helper.urls2links(this.clearText);
helper.urls2links(this.prettyPrint);
if (typeof prettyPrint == 'function') prettyPrint();
} }
catch(err) catch(err)
{ {
@ -554,7 +607,6 @@ $(function() {
} }
// Display paste expiration / for your eyes only. // Display paste expiration / for your eyes only.
var content = this.remainingTime.contents();
if (comments[0].meta.expire_date) if (comments[0].meta.expire_date)
{ {
var expiration = helper.secondsToHuman(comments[0].meta.remaining_time), var expiration = helper.secondsToHuman(comments[0].meta.remaining_time),
@ -562,7 +614,7 @@ $(function() {
'This document will expire in %d ' + expiration[1] + '.', 'This document will expire in %d ' + expiration[1] + '.',
'This document will expire in %d ' + expiration[1] + 's.' 'This document will expire in %d ' + expiration[1] + 's.'
]; ];
content[content.length - 1].nodeValue = ' ' + i18n._(expirationLabel, expiration[0]); helper.setMessage(this.remainingTime, i18n._(expirationLabel, expiration[0]));
this.remainingTime.removeClass('foryoureyesonly') this.remainingTime.removeClass('foryoureyesonly')
.removeClass('hidden'); .removeClass('hidden');
} }
@ -572,9 +624,9 @@ $(function() {
.fail(function() { .fail(function() {
zerobin.showError(i18n._('Could not delete the paste, it was not stored in burn after reading mode.')); zerobin.showError(i18n._('Could not delete the paste, it was not stored in burn after reading mode.'));
}); });
content[content.length - 1].nodeValue = ' ' + i18n._( helper.setMessage(this.remainingTime, i18n._(
'FOR YOUR EYES ONLY. Don\'t close this window, this message can\'t be displayed again.' 'FOR YOUR EYES ONLY. Don\'t close this window, this message can\'t be displayed again.'
); ));
this.remainingTime.addClass('foryoureyesonly') this.remainingTime.addClass('foryoureyesonly')
.removeClass('hidden'); .removeClass('hidden');
// Discourage cloning (as it can't really be prevented). // Discourage cloning (as it can't really be prevented).
@ -776,6 +828,7 @@ $(function() {
var data_to_send = { var data_to_send = {
data: cipherdata, data: cipherdata,
expire: $('#pasteExpiration').val(), expire: $('#pasteExpiration').val(),
formatter: $('#pasteFormatter').val(),
burnafterreading: this.burnAfterReading.is(':checked') ? 1 : 0, burnafterreading: this.burnAfterReading.is(':checked') ? 1 : 0,
opendiscussion: this.openDiscussion.is(':checked') ? 1 : 0 opendiscussion: this.openDiscussion.is(':checked') ? 1 : 0
}; };
@ -793,14 +846,11 @@ $(function() {
zerobin.pasteResult.removeClass('hidden'); zerobin.pasteResult.removeClass('hidden');
// We pre-select the link so that the user only has to [Ctrl]+[c] the link. // We pre-select the link so that the user only has to [Ctrl]+[c] the link.
helper.selectText('pasteurl'); helper.selectText('pasteurl');
zerobin.showStatus('', false);
helper.setElementText(zerobin.clearText, zerobin.message.val()); helper.setElementText(zerobin.clearText, zerobin.message.val());
helper.setElementText(zerobin.prettyPrint, zerobin.message.val()); helper.setElementText(zerobin.prettyPrint, zerobin.message.val());
// Convert URLs to clickable links. zerobin.formatPaste(data_to_send.formatter);
helper.urls2links(zerobin.clearText);
helper.urls2links(zerobin.prettyPrint);
zerobin.showStatus('', false);
if (typeof prettyPrint == 'function') prettyPrint();
} }
else if (data.status==1) else if (data.status==1)
{ {
@ -831,6 +881,7 @@ $(function() {
this.prettyMessage.addClass('hidden'); this.prettyMessage.addClass('hidden');
this.sendButton.removeClass('hidden'); this.sendButton.removeClass('hidden');
this.expiration.removeClass('hidden'); this.expiration.removeClass('hidden');
this.formatter.removeClass('hidden');
this.burnAfterReadingOption.removeClass('hidden'); this.burnAfterReadingOption.removeClass('hidden');
this.openDisc.removeClass('hidden'); this.openDisc.removeClass('hidden');
this.newButton.removeClass('hidden'); this.newButton.removeClass('hidden');
@ -858,6 +909,7 @@ $(function() {
this.rawTextButton.removeClass('hidden'); this.rawTextButton.removeClass('hidden');
this.expiration.addClass('hidden'); this.expiration.addClass('hidden');
this.formatter.addClass('hidden');
this.burnAfterReadingOption.addClass('hidden'); this.burnAfterReadingOption.addClass('hidden');
this.openDisc.addClass('hidden'); this.openDisc.addClass('hidden');
this.newButton.removeClass('hidden'); this.newButton.removeClass('hidden');
@ -953,8 +1005,7 @@ $(function() {
else else
{ {
this.errorMessage.removeClass('hidden'); this.errorMessage.removeClass('hidden');
var content = this.errorMessage.contents(); helper.setMessage(this.errorMessage, message);
content[content.length - 1].nodeValue = ' ' + message;
} }
this.replyStatus.addClass('errorMessage').text(message); this.replyStatus.addClass('errorMessage').text(message);
}, },
@ -1018,6 +1069,7 @@ $(function() {
this.discussion = $('#discussion'); this.discussion = $('#discussion');
this.errorMessage = $('#errormessage'); this.errorMessage = $('#errormessage');
this.expiration = $('#expiration'); this.expiration = $('#expiration');
this.formatter = $('#formatter');
this.message = $('#message'); this.message = $('#message');
this.newButton = $('#newbutton'); this.newButton = $('#newbutton');
this.openDisc = $('#opendisc'); this.openDisc = $('#opendisc');

View File

@ -49,6 +49,14 @@ class zerobin
*/ */
private $_data = ''; private $_data = '';
/**
* formatter
*
* @access private
* @var string
*/
private $_formatter = 'plaintext';
/** /**
* error message * error message
* *
@ -237,7 +245,7 @@ class zerobin
$meta = array(); $meta = array();
// Read expiration date // Read expiration date
if (!empty($_POST['expire'])) if (array_key_exists('expire', $_POST) && !empty($_POST['expire']))
{ {
$selected_expire = (string) $_POST['expire']; $selected_expire = (string) $_POST['expire'];
if (array_key_exists($selected_expire, $this->_conf['expire_options'])) if (array_key_exists($selected_expire, $this->_conf['expire_options']))
@ -252,7 +260,7 @@ class zerobin
} }
// Destroy the paste when it is read. // Destroy the paste when it is read.
if (!empty($_POST['burnafterreading'])) if (array_key_exists('burnafterreading', $_POST) && !empty($_POST['burnafterreading']))
{ {
$burnafterreading = $_POST['burnafterreading']; $burnafterreading = $_POST['burnafterreading'];
if ($burnafterreading !== '0') if ($burnafterreading !== '0')
@ -263,7 +271,11 @@ class zerobin
} }
// Read open discussion flag. // Read open discussion flag.
if ($this->_conf['main']['discussion'] && !empty($_POST['opendiscussion'])) if (
$this->_getMainConfig('discussion', true) &&
array_key_exists('opendiscussion', $_POST) &&
!empty($_POST['opendiscussion'])
)
{ {
$opendiscussion = $_POST['opendiscussion']; $opendiscussion = $_POST['opendiscussion'];
if ($opendiscussion !== '0') if ($opendiscussion !== '0')
@ -273,6 +285,17 @@ class zerobin
} }
} }
// Read formatter flag.
if (array_key_exists('formatter', $_POST) && !empty($_POST['formatter']))
{
$formatter = $_POST['formatter'];
if (!array_key_exists($formatter, $this->_conf['formatter_options']))
{
$formatter = $this->_getMainConfig('defaultformatter', 'syntaxhighlighting');
}
$meta['formatter'] = $formatter;
}
// You can't have an open discussion on a "Burn after reading" paste: // You can't have an open discussion on a "Burn after reading" paste:
if (isset($meta['burnafterreading'])) unset($meta['opendiscussion']); if (isset($meta['burnafterreading'])) unset($meta['opendiscussion']);
@ -541,6 +564,13 @@ class zerobin
$this->_model()->readComments($dataid) $this->_model()->readComments($dataid)
); );
} }
// set formatter for for the view.
if (!property_exists($paste->meta, 'formatter'))
{
$paste->meta->formatter = $this->_getMainConfig('defaultformatter', 'syntaxhighlighting');
}
$this->_data = json_encode($messages); $this->_data = json_encode($messages);
} }
} }
@ -579,10 +609,14 @@ class zerobin
// label all the expiration options // label all the expiration options
$expire = array(); $expire = array();
foreach ($this->_conf['expire_options'] as $time => $seconds) { foreach ($this->_conf['expire_options'] as $time => $seconds)
{
$expire[$time] = ($seconds == 0) ? i18n::_(ucfirst($time)): filter::time_humanreadable($time); $expire[$time] = ($seconds == 0) ? i18n::_(ucfirst($time)): filter::time_humanreadable($time);
} }
// translate all the formatter options
$formatters = array_map(array('i18n', 'translate'), $this->_conf['formatter_options']);
$page = new RainTPL; $page = new RainTPL;
$page::$path_replace = false; $page::$path_replace = false;
// we escape it here because ENT_NOQUOTES can't be used in RainTPL templates // we escape it here because ENT_NOQUOTES can't be used in RainTPL templates
@ -592,8 +626,11 @@ class zerobin
$page->assign('VERSION', self::VERSION); $page->assign('VERSION', self::VERSION);
$page->assign('DISCUSSION', $this->_getMainConfig('discussion', true)); $page->assign('DISCUSSION', $this->_getMainConfig('discussion', true));
$page->assign('OPENDISCUSSION', $this->_getMainConfig('opendiscussion', true)); $page->assign('OPENDISCUSSION', $this->_getMainConfig('opendiscussion', true));
$page->assign('SYNTAXHIGHLIGHTING', $this->_getMainConfig('syntaxhighlighting', true)); $page->assign('MARKDOWN', array_key_exists('markdown', $formatters));
$page->assign('SYNTAXHIGHLIGHTING', array_key_exists('syntaxhighlighting', $formatters));
$page->assign('SYNTAXHIGHLIGHTINGTHEME', $this->_getMainConfig('syntaxhighlightingtheme', '')); $page->assign('SYNTAXHIGHLIGHTINGTHEME', $this->_getMainConfig('syntaxhighlightingtheme', ''));
$page->assign('FORMATTER', $formatters);
$page->assign('FORMATTERDEFAULT', $this->_getMainConfig('defaultformatter', 'syntaxhighlighting'));
$page->assign('NOTICE', i18n::_($this->_getMainConfig('notice', ''))); $page->assign('NOTICE', i18n::_($this->_getMainConfig('notice', '')));
$page->assign('BURNAFTERREADINGSELECTED', $this->_getMainConfig('burnafterreadingselected', false)); $page->assign('BURNAFTERREADINGSELECTED', $this->_getMainConfig('burnafterreadingselected', false));
$page->assign('PASSWORD', $this->_getMainConfig('password', true)); $page->assign('PASSWORD', $this->_getMainConfig('password', true));

View File

@ -17,7 +17,8 @@
<script type="text/javascript" src="js/rawdeflate-0.5.js"></script> <script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
<script type="text/javascript" src="js/rawinflate-0.3.js"></script> <script type="text/javascript" src="js/rawinflate-0.3.js"></script>
<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script>{if="$SYNTAXHIGHLIGHTING"} <script type="text/javascript" src="js/bootstrap-3.3.5.js"></script>{if="$SYNTAXHIGHLIGHTING"}
<script type="text/javascript" src="js/prettify.js?{$VERSION|rawurlencode}"></script>{/if} <script type="text/javascript" src="js/prettify.js?{$VERSION|rawurlencode}"></script>{/if}{if="$MARKDOWN"}
<script type="text/javascript" src="js/showdown.js?{$VERSION|rawurlencode}"></script>{/if}
<script type="text/javascript" src="js/zerobin.js?{$VERSION|rawurlencode}"></script> <script type="text/javascript" src="js/zerobin.js?{$VERSION|rawurlencode}"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">#ienotice {display:block !important;} #oldienotice {display:block !important;}</style> <style type="text/css">#ienotice {display:block !important;} #oldienotice {display:block !important;}</style>
@ -80,6 +81,17 @@
<input type="password" id="passwordinput" placeholder="{function="t('Password (recommended)')"}" class="form-control" size="19"/> <input type="password" id="passwordinput" placeholder="{function="t('Password (recommended)')"}" class="form-control" size="19"/>
</div> </div>
</li>{/if} </li>{/if}
<li class="dropdown">
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
{loop="FORMATTER"}
<option value="{$key}"{if="$key == $FORMATTERDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
</select>
<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{function="t('Format')"}: <span id="pasteFormatterDisplay">{$FORMATTER[$FORMATTERDEFAULT]}</span> <span class="caret"></span></a>
<ul class="dropdown-menu">
{loop="FORMATTER"}
<li><a href="#" onclick="$('#pasteFormatter').val('{$key}');$('#pasteFormatterDisplay').text('{$value}');return false;">{$value}</a></li>{/loop}
</ul>
</li>
</ul> </ul>
<ul class="nav navbar-nav pull-right"> <ul class="nav navbar-nav pull-right">
<li> <li>

View File

@ -12,7 +12,8 @@
<script type="text/javascript" src="js/base64-{$BASE64JSVERSION}.js"></script> <script type="text/javascript" src="js/base64-{$BASE64JSVERSION}.js"></script>
<script type="text/javascript" src="js/rawdeflate-0.5.js"></script> <script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
<script type="text/javascript" src="js/rawinflate-0.3.js"></script>{if="$SYNTAXHIGHLIGHTING"} <script type="text/javascript" src="js/rawinflate-0.3.js"></script>{if="$SYNTAXHIGHLIGHTING"}
<script type="text/javascript" src="js/prettify.js?{$VERSION|rawurlencode}"></script>{/if} <script type="text/javascript" src="js/prettify.js?{$VERSION|rawurlencode}"></script>{/if}{if="$MARKDOWN"}
<script type="text/javascript" src="js/showdown.js?{$VERSION|rawurlencode}"></script>{/if}
<script type="text/javascript" src="js/zerobin.js?{$VERSION|rawurlencode}"></script> <script type="text/javascript" src="js/zerobin.js?{$VERSION|rawurlencode}"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
@ -24,9 +25,9 @@
{function="t('ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/elrido/ZeroBin/wiki">project page</a>.')"}<br />{if="strlen($NOTICE)"} {function="t('ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/elrido/ZeroBin/wiki">project page</a>.')"}<br />{if="strlen($NOTICE)"}
<span class="blink"></span> {$NOTICE}{/if} <span class="blink"></span> {$NOTICE}{/if}
</div> </div>
<h1 class="reloadlink">{function="t('ZeroBin')"}</h1><br /> <h1 class="title reloadlink">{function="t('ZeroBin')"}</h1><br />
<h2>{function="t('Because ignorance is bliss')"}</h2><br /> <h2 class="title">{function="t('Because ignorance is bliss')"}</h2><br />
<h3>{$VERSION}</h3> <h3 class="title">{$VERSION}</h3>
<div id="noscript" class="nonworking">{function="t('Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.')"}</div> <div id="noscript" class="nonworking">{function="t('Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.')"}</div>
<div id="oldienotice" class="nonworking">{function="t('ZeroBin requires a modern browser to work.')"}</div> <div id="oldienotice" class="nonworking">{function="t('ZeroBin requires a modern browser to work.')"}</div>
<div id="ienotice">{function="t('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:')"} <div id="ienotice">{function="t('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:')"}
@ -63,6 +64,12 @@
<div id="password" class="hidden"> <div id="password" class="hidden">
<input type="password" id="passwordinput" placeholder="{function="t('Password (recommended)')"}" size="32" /> <input type="password" id="passwordinput" placeholder="{function="t('Password (recommended)')"}" size="32" />
</div>{/if} </div>{/if}
<div id="formatter" class="button hidden">{function="t('Format')"}:
<select id="pasteFormatter" name="pasteFormatter">
{loop="FORMATTER"}
<option value="{$key}"{if="$key == $FORMATTERDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
</select>
</div>
</div> </div>
<div id="pasteresult" class="hidden"> <div id="pasteresult" class="hidden">
<div id="deletelink"></div> <div id="deletelink"></div>
@ -77,7 +84,7 @@
</section> </section>
<section> <section>
<div id="discussion" class="hidden"> <div id="discussion" class="hidden">
<h4>{function="t('Discussion')"}</h4> <h4 class="title">{function="t('Discussion')"}</h4>
<div id="comments"></div> <div id="comments"></div>
</div> </div>
</section> </section>

View File

@ -33,6 +33,7 @@ class RainTPLTest extends PHPUnit_Framework_TestCase
$page->assign('VERSION', self::$version); $page->assign('VERSION', self::$version);
$page->assign('DISCUSSION', true); $page->assign('DISCUSSION', true);
$page->assign('OPENDISCUSSION', true); $page->assign('OPENDISCUSSION', true);
$page->assign('MARKDOWN', true);
$page->assign('SYNTAXHIGHLIGHTING', true); $page->assign('SYNTAXHIGHLIGHTING', true);
$page->assign('SYNTAXHIGHLIGHTINGTHEME', 'sons-of-obsidian'); $page->assign('SYNTAXHIGHLIGHTINGTHEME', 'sons-of-obsidian');
$page->assign('BURNAFTERREADINGSELECTED', false); $page->assign('BURNAFTERREADINGSELECTED', false);

View File

@ -8,6 +8,7 @@ class zerobinTest extends PHPUnit_Framework_TestCase
'meta' => array( 'meta' => array(
'postdate' => 1344803344, 'postdate' => 1344803344,
'opendiscussion' => true, 'opendiscussion' => true,
'formatter' => 'syntaxhighlighting',
), ),
); );
@ -202,6 +203,7 @@ class zerobinTest extends PHPUnit_Framework_TestCase
helper::createIniFile($this->_conf, $options); helper::createIniFile($this->_conf, $options);
$_POST = self::$paste; $_POST = self::$paste;
$_POST['expire'] = '5min'; $_POST['expire'] = '5min';
$_POST['formatter'] = 'foo';
$_SERVER['REMOTE_ADDR'] = '::1'; $_SERVER['REMOTE_ADDR'] = '::1';
ob_start(); ob_start();
new zerobin; new zerobin;