Merge branch 'master' into dev
Conflicts: isso/views/comments.py
This commit is contained in:
commit
01d86881ca
25
CHANGES.rst
25
CHANGES.rst
@ -7,12 +7,35 @@ Changelog for Isso
|
|||||||
- Nothing changed yet.
|
- Nothing changed yet.
|
||||||
|
|
||||||
|
|
||||||
0.9.5 (unreleased)
|
0.9.6 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
- Nothing changed yet.
|
- Nothing changed yet.
|
||||||
|
|
||||||
|
|
||||||
|
0.9.5 (2014-08-10)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- prevent no-break space ( ) insertion to enable manual line breaks using
|
||||||
|
two trailing spaces (as per Markdown convention), #112
|
||||||
|
|
||||||
|
- limit request size to 256 kb, #107
|
||||||
|
|
||||||
|
Previously unlimited or limited by proxy server). 256 kb is a rough
|
||||||
|
approximation of the next database schema with comments limited to 65535
|
||||||
|
characters and additional fields.
|
||||||
|
|
||||||
|
- add support for logging to file, #103
|
||||||
|
|
||||||
|
[general]
|
||||||
|
log-file =
|
||||||
|
|
||||||
|
- show timestamp when hovering <time>, #104
|
||||||
|
|
||||||
|
- fix a regression when editing comments with multiple paragraphs introduced
|
||||||
|
in 0.9.3 which would HTML escape manually inserted linebreaks.
|
||||||
|
|
||||||
|
|
||||||
0.9.4 (2014-07-09)
|
0.9.4 (2014-07-09)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ preferably in the script tag which embeds the JS:
|
|||||||
data-isso-max-comments-nested="5"
|
data-isso-max-comments-nested="5"
|
||||||
data-isso-reveal-on-click="5"
|
data-isso-reveal-on-click="5"
|
||||||
data-isso-avatar="true"
|
data-isso-avatar="true"
|
||||||
data-avatar-bg="#f0f0f0"
|
data-isso-avatar-bg="#f0f0f0"
|
||||||
data-avatar-fg="#9abf88 #5698c4 #e279a3 #9163b6 ..."
|
data-isso-avatar-fg="#9abf88 #5698c4 #e279a3 #9163b6 ..."
|
||||||
src="/prefix/js/embed.js"></script>
|
src="/prefix/js/embed.js"></script>
|
||||||
|
|
||||||
Furthermore you can override the automatic title detection inside
|
Furthermore you can override the automatic title detection inside
|
||||||
|
@ -44,6 +44,7 @@ session key and hostname. Here are the default values for this section:
|
|||||||
host =
|
host =
|
||||||
max-age = 15m
|
max-age = 15m
|
||||||
notify = stdout
|
notify = stdout
|
||||||
|
log-file =
|
||||||
|
|
||||||
dbpath
|
dbpath
|
||||||
file location to the SQLite3 database, highly recommended to change this
|
file location to the SQLite3 database, highly recommended to change this
|
||||||
@ -86,6 +87,9 @@ notify
|
|||||||
Send notifications via SMTP on new comments with activation (if
|
Send notifications via SMTP on new comments with activation (if
|
||||||
moderated) and deletion links.
|
moderated) and deletion links.
|
||||||
|
|
||||||
|
log-file
|
||||||
|
Log console messages to file instead of standard out.
|
||||||
|
|
||||||
|
|
||||||
.. _CORS: https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS
|
.. _CORS: https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS
|
||||||
|
|
||||||
|
@ -139,6 +139,8 @@ Prebuilt Packages
|
|||||||
* Arch Linux: https://aur.archlinux.org/packages/isso/
|
* Arch Linux: https://aur.archlinux.org/packages/isso/
|
||||||
– install with `yaourt isso`.
|
– install with `yaourt isso`.
|
||||||
|
|
||||||
|
* Docker Image: https://registry.hub.docker.com/u/bl4n/isso/
|
||||||
|
|
||||||
Install from Source
|
Install from Source
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ from isso.utils import http, JSONRequest, html, hash
|
|||||||
|
|
||||||
from isso.ext.notifications import Stdout, SMTP
|
from isso.ext.notifications import Stdout, SMTP
|
||||||
|
|
||||||
logging.getLogger('werkzeug').setLevel(logging.ERROR)
|
logging.getLogger('werkzeug').setLevel(logging.WARN)
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
format="%(asctime)s %(levelname)s: %(message)s")
|
format="%(asctime)s %(levelname)s: %(message)s")
|
||||||
@ -270,6 +270,15 @@ def main():
|
|||||||
migrate.dispatch(tc, cc, args.type, args.dump)
|
migrate.dispatch(tc, cc, args.type, args.dump)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
if conf.get("general", "log-file"):
|
||||||
|
handler = logging.FileHandler(conf.get("general", "log-file"))
|
||||||
|
|
||||||
|
logger.addHandler(handler)
|
||||||
|
logging.getLogger("werkzeug").addHandler(handler)
|
||||||
|
|
||||||
|
logger.propagate = False
|
||||||
|
logging.getLogger("werkzeug").propagate = False
|
||||||
|
|
||||||
if not any(conf.getiter("general", "host")):
|
if not any(conf.getiter("general", "host")):
|
||||||
logger.error("No website(s) configured, Isso won't work.")
|
logger.error("No website(s) configured, Isso won't work.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -17,7 +17,7 @@ define({
|
|||||||
"comment-queued": "Commentaire en attente de modération.",
|
"comment-queued": "Commentaire en attente de modération.",
|
||||||
"comment-anonymous": "Anonyme",
|
"comment-anonymous": "Anonyme",
|
||||||
"comment-hidden": "1 caché\n{{ n }} cachés",
|
"comment-hidden": "1 caché\n{{ n }} cachés",
|
||||||
"date-now": "À l'instant'",
|
"date-now": "À l'instant",
|
||||||
"date-minute": "Il y a une minute\nIl y a {{ n }} minutes",
|
"date-minute": "Il y a une minute\nIl y a {{ n }} minutes",
|
||||||
"date-hour": "Il y a une heure\nIl y a {{ n }} heures ",
|
"date-hour": "Il y a une heure\nIl y a {{ n }} heures ",
|
||||||
"date-day": "Hier\nIl y a {{ n }} jours",
|
"date-day": "Hier\nIl y a {{ n }} jours",
|
||||||
|
@ -101,7 +101,7 @@ define(["app/dom", "app/utils", "app/config", "app/api", "app/jade", "app/i18n",
|
|||||||
|
|
||||||
// update datetime every 60 seconds
|
// update datetime every 60 seconds
|
||||||
var refresh = function() {
|
var refresh = function() {
|
||||||
$(".permalink > date", el).textContent = utils.ago(
|
$(".permalink > time", el).textContent = utils.ago(
|
||||||
globals.offset.localTime(), new Date(parseInt(comment.created, 10) * 1000));
|
globals.offset.localTime(), new Date(parseInt(comment.created, 10) * 1000));
|
||||||
setTimeout(refresh, 60*1000);
|
setTimeout(refresh, 60*1000);
|
||||||
};
|
};
|
||||||
|
@ -21,6 +21,13 @@ define(["libjs-jade-runtime", "app/utils", "jade!app/text/postbox", "jade!app/te
|
|||||||
load("comment-loader", tt_comment_loader);
|
load("comment-loader", tt_comment_loader);
|
||||||
|
|
||||||
set("bool", function(arg) { return arg ? true : false; });
|
set("bool", function(arg) { return arg ? true : false; });
|
||||||
|
set("humanize", function(date) {
|
||||||
|
if (typeof date !== "object") {
|
||||||
|
date = new Date(parseInt(date, 10) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return date.toString();
|
||||||
|
});
|
||||||
set("datetime", function(date) {
|
set("datetime", function(date) {
|
||||||
if (typeof date !== "object") {
|
if (typeof date !== "object") {
|
||||||
date = new Date(parseInt(date, 10) * 1000);
|
date = new Date(parseInt(date, 10) * 1000);
|
||||||
@ -30,7 +37,11 @@ define(["libjs-jade-runtime", "app/utils", "jade!app/text/postbox", "jade!app/te
|
|||||||
date.getUTCFullYear(),
|
date.getUTCFullYear(),
|
||||||
utils.pad(date.getUTCMonth(), 2),
|
utils.pad(date.getUTCMonth(), 2),
|
||||||
utils.pad(date.getUTCDay(), 2)
|
utils.pad(date.getUTCDay(), 2)
|
||||||
].join("-");
|
].join("-") + "T" + [
|
||||||
|
utils.pad(date.getUTCHours(), 2),
|
||||||
|
utils.pad(date.getUTCMinutes(), 2),
|
||||||
|
utils.pad(date.getUTCSeconds(), 2)
|
||||||
|
].join(":") + "Z";
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
define(["vendor/markup", "app/config", "app/i18n", "app/text/svg"], function(Mark, config, i18n, svg) {
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
|
|
||||||
// circumvent https://github.com/adammark/Markup.js/issues/22
|
|
||||||
function merge(obj) {
|
|
||||||
var result = {};
|
|
||||||
for (var prefix in obj) {
|
|
||||||
for (var attrname in obj[prefix]) {
|
|
||||||
result[prefix + "-" + attrname] = obj[prefix][attrname];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mark.delimiter = ":";
|
|
||||||
Mark.includes = merge({
|
|
||||||
conf: config,
|
|
||||||
i18n: i18n[i18n.lang],
|
|
||||||
svg: svg
|
|
||||||
});
|
|
||||||
|
|
||||||
Mark.pipes.datetime = function(date) {
|
|
||||||
if (typeof date !== "object") {
|
|
||||||
date = new Date(parseInt(date, 10) * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [date.getUTCFullYear(), pad(date.getUTCMonth(), 2), pad(date.getUTCDay(), 2)].join("-");
|
|
||||||
};
|
|
||||||
|
|
||||||
Mark.pipes.substract = function(a, b) {
|
|
||||||
return parseInt(a, 10) - parseInt(b, 10);
|
|
||||||
};
|
|
||||||
|
|
||||||
var strip = function(string) {
|
|
||||||
// allow whitespace between Markup.js delimiters such as
|
|
||||||
// {{ var | pipe : arg }} instead of {{var|pipe:arg}}
|
|
||||||
return string.replace(/\{\{\s*(.+?)\s*\}\}/g, function(match, val) {
|
|
||||||
return ("{{" + val + "}}").replace(/\s*\|\s*/g, "|")
|
|
||||||
.replace(/\s*\:\s*/g, ":");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
up: function(template, context) {
|
|
||||||
return Mark.up(strip(template), context);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
@ -12,7 +12,7 @@ div(class='isso-comment' id='isso-#{comment.id}')
|
|||||||
= bool(comment.author) ? comment.author : i18n('comment-anonymous')
|
= bool(comment.author) ? comment.author : i18n('comment-anonymous')
|
||||||
span(class="spacer") •
|
span(class="spacer") •
|
||||||
a(class='permalink' href='#isso-#{comment.id}')
|
a(class='permalink' href='#isso-#{comment.id}')
|
||||||
date(datetime='#{datetime(comment.created)}')
|
time(title='#{humanize(comment.created)}' datetime='#{datetime(comment.created)}')
|
||||||
span(class='note')
|
span(class='note')
|
||||||
= comment.mode == 2 ? i18n('comment-queued') : comment.mode == 4 ? i18n('comment-deleted') : ''
|
= comment.mode == 2 ? i18n('comment-queued') : comment.mode == 4 ? i18n('comment-deleted') : ''
|
||||||
|
|
||||||
|
@ -57,13 +57,15 @@ define(["app/i18n"], function(i18n) {
|
|||||||
var _ = document.createElement("div");
|
var _ = document.createElement("div");
|
||||||
_.innerHTML = html.replace(/<div><br><\/div>/gi, '<br>')
|
_.innerHTML = html.replace(/<div><br><\/div>/gi, '<br>')
|
||||||
.replace(/<div>/gi,'<br>')
|
.replace(/<div>/gi,'<br>')
|
||||||
.replace(/<br>/gi, '\n');
|
.replace(/<br>/gi, '\n')
|
||||||
|
.replace(/ /gi, ' ');
|
||||||
return _.textContent.trim();
|
return _.textContent.trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
var detext = function(text) {
|
var detext = function(text) {
|
||||||
return escape(text.replace(/\n\n/gi, '<br><div><br></div>')
|
text = escape(text);
|
||||||
.replace(/\n/gi, '<br>'));
|
return text.replace(/\n\n/gi, '<br><div><br></div>')
|
||||||
|
.replace(/\n/gi, '<br>');
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -8,9 +8,11 @@ werkzeug = pkg_resources.get_distribution("werkzeug")
|
|||||||
import json
|
import json
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from werkzeug.wrappers import Request, Response
|
from werkzeug.wrappers import Response
|
||||||
from werkzeug.exceptions import BadRequest
|
from werkzeug.exceptions import BadRequest
|
||||||
|
|
||||||
|
from isso.wsgi import Request
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ipaddress
|
import ipaddress
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -17,6 +17,7 @@ except ImportError:
|
|||||||
from BaseHTTPServer import HTTPServer
|
from BaseHTTPServer import HTTPServer
|
||||||
|
|
||||||
from werkzeug.serving import WSGIRequestHandler
|
from werkzeug.serving import WSGIRequestHandler
|
||||||
|
from werkzeug.wrappers import Request as _Request
|
||||||
from werkzeug.datastructures import Headers
|
from werkzeug.datastructures import Headers
|
||||||
|
|
||||||
from isso.compat import string_types
|
from isso.compat import string_types
|
||||||
@ -148,6 +149,14 @@ class CORSMiddleware(object):
|
|||||||
return self.app(environ, add_cors_headers)
|
return self.app(environ, add_cors_headers)
|
||||||
|
|
||||||
|
|
||||||
|
class Request(_Request):
|
||||||
|
|
||||||
|
# Assuming UTF-8, comments with 65536 characters would consume
|
||||||
|
# 128 kb memory. The remaining 128 kb cover additional parameters
|
||||||
|
# and WSGI headers.
|
||||||
|
max_content_length = 256 * 1024
|
||||||
|
|
||||||
|
|
||||||
class SocketWSGIRequestHandler(WSGIRequestHandler):
|
class SocketWSGIRequestHandler(WSGIRequestHandler):
|
||||||
|
|
||||||
def run_wsgi(self):
|
def run_wsgi(self):
|
||||||
|
@ -43,6 +43,9 @@ max-age = 15m
|
|||||||
# moderated) and deletion links.
|
# moderated) and deletion links.
|
||||||
notify = stdout
|
notify = stdout
|
||||||
|
|
||||||
|
# Log console messages to file instead of standard out.
|
||||||
|
log-file =
|
||||||
|
|
||||||
|
|
||||||
[moderation]
|
[moderation]
|
||||||
# enable comment moderation queue. This option only affects new comments.
|
# enable comment moderation queue. This option only affects new comments.
|
||||||
|
Loading…
Reference in New Issue
Block a user