summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@jelmer.uk>2016-10-01 02:22:24 +0000
committerJelmer Vernooij <jelmer@jelmer.uk>2016-10-01 02:22:24 +0000
commitc914b1d44430ff2ea7e0e8ee35688414ebb76979 (patch)
tree7d34f27bd107f6d359bc528039a91101a1fb86a9
parent6bcd17a8f76c6d4ae0fe71f4db7e22092bc4bdc0 (diff)
parentb825e27335b2872784b1ecb49d6f390640af092a (diff)
Merge tag 'upstream/0.10.6' into unstable
Upstream version 0.10.6
-rw-r--r--.gitignore92
-rw-r--r--CHANGES.rst35
-rw-r--r--CONTRIBUTORS.txt7
-rw-r--r--docs/docs/configuration/client.rst30
-rw-r--r--docs/docs/configuration/server.rst7
-rw-r--r--isso/__init__.py2
-rw-r--r--isso/css/isso.css3
-rw-r--r--isso/db/spam.py4
-rw-r--r--isso/js/app/config.js4
-rw-r--r--isso/js/app/dom.js7
-rw-r--r--isso/js/app/globals.js4
-rw-r--r--isso/js/app/i18n.js14
-rw-r--r--isso/js/app/i18n/fi.js30
-rw-r--r--isso/js/app/i18n/zh_CN.js8
-rw-r--r--isso/js/app/i18n/zh_TW.js6
-rw-r--r--isso/js/app/isso.js49
-rw-r--r--isso/js/app/text/comment.jade2
-rw-r--r--isso/tests/test_comments.py8
-rw-r--r--isso/tests/test_guard.py23
-rw-r--r--isso/views/comments.py26
-rw-r--r--setup.py2
-rw-r--r--share/isso.conf5
22 files changed, 322 insertions, 46 deletions
diff --git a/.gitignore b/.gitignore
index d00e82d..ae5ee37 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,95 @@
/docs/_static/css/site.css
/pip-selfcheck.json
+
+# github/gitignore
+Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+.hypothesis/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# IPython Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# dotenv
+.env
+
+# virtualenv
+.venv/
+venv/
+ENV/
+
+# Spyder project settings
+.spyderproject
+
+# Rope project settings
+.ropeproject
diff --git a/CHANGES.rst b/CHANGES.rst
index 732cc63..2bf9c81 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,11 +1,44 @@
Changelog for Isso
==================
+0.10.6 (2016-09-22)
+-------------------
+
+- fix missing configuration field
+
+
+0.10.5 (2016-09-20)
+-------------------
+
+- add support for different vote levels, #260
+
+ List of vote levels used to customize comment appearance based on score.
+ Provide a comma-separated values (eg. `"0,5,10,25,100"`) or a JSON array (eg.
+ `"[-5,5,15]"`).
+
+ For example, the value `"-5,5"` will cause each `isso-comment` to be given
+ one of these 3 classes:
+
+ - `isso-vote-level-0` for scores lower than `-5`
+ - `isso-vote-level-1` for scores between `-5` and `4`
+ - `isso-vote-level-2` for scores of `5` and greater
+
+ These classes can then be used to customize the appearance of comments (eg.
+ put a star on popular comments).
+
+- add new post preview API endpoint, #254
+
+- add an option for mandatory author, #257
+
+- clients can now use `data-title` to get the HTML title for a new page, #252
+
+- add finish translation and other minor bugfixes
+
+
0.10.4 (2016-04-12)
-------------------
- fix wrapper attribute when using data-isso-require-mail="true", #238
-
- fix reponse for OPTIONS response on Python 3, #242
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index cffbfc2..0b5e649 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -51,5 +51,12 @@ In chronological order:
* Added configuration to require email addresses (no validation)
* Fix Vagrantfile
+* Benoît Latinier <benoit@latinier.fr>
+ * Fix thread discovery
+ * Added mandatory author
+
+* Ivan Pantic <ivanpantic82@gmail.com>
+ * Added vote levels
+
* [Your name or handle] <[email or website]>
* [Brief summary of your changes]
diff --git a/docs/docs/configuration/client.rst b/docs/docs/configuration/client.rst
index 3eece63..ea7487a 100644
--- a/docs/docs/configuration/client.rst
+++ b/docs/docs/configuration/client.rst
@@ -10,6 +10,7 @@ preferably in the script tag which embeds the JS:
data-isso-css="true"
data-isso-lang="ru"
data-isso-reply-to-self="false"
+ data-isso-require-author="false"
data-isso-require-email="false"
data-isso-max-comments-top="10"
data-isso-max-comments-nested="5"
@@ -18,6 +19,7 @@ preferably in the script tag which embeds the JS:
data-isso-avatar-bg="#f0f0f0"
data-isso-avatar-fg="#9abf88 #5698c4 #e279a3 #9163b6 ..."
data-isso-vote="true"
+ data-vote-levels=""
src="/prefix/js/embed.js"></script>
Furthermore you can override the automatic title detection inside
@@ -63,6 +65,11 @@ data-isso-reply-to-self
Set to `true` when spam guard is configured with `reply-to-self = true`.
+data-isso-require-author
+------------------------
+
+Set to `true` when spam guard is configured with `require-author = true`.
+
data-isso-require-email
-----------------------
@@ -104,14 +111,27 @@ data-isso-vote
Enable or disable voting feature on the client side.
+data-isso-vote-levels
+---------------------
+
+List of vote levels used to customize comment appearance based on score.
+Provide a comma-separated values (eg. `"0,5,10,25,100"`) or a JSON array (eg. `"[-5,5,15]"`).
+
+For example, the value `"-5,5"` will cause each `isso-comment` to be given one of these 3 classes:
+
+- `isso-vote-level-0` for scores lower than `-5`
+- `isso-vote-level-1` for scores between `-5` and `4`
+- `isso-vote-level-2` for scores of `5` and greater
+
+These classes can then be used to customize the appearance of comments (eg. put a star on popular comments)
+
data-isso-id
------------
-Broken – do not use. https://github.com/posativ/isso/issues/27
-
-Set a custom thread id, defaults to current URI. If you use a comment counter,
-add this attribute to the link tag, too.
+Set a custom thread id, defaults to current URI. This attribute needs
+to be used with the data-title attribute in order to work.
+If you use a comment counter, add this attribute to the link tag, too.
.. code-block:: html
- <section data-isso-id="test.abc" id="isso-thread"></section>
+ <section data-title="Yay!" data-isso-id="test.abc" id="isso-thread"></section>
diff --git a/docs/docs/configuration/server.rst b/docs/docs/configuration/server.rst
index 86d1b7f..cb39ccd 100644
--- a/docs/docs/configuration/server.rst
+++ b/docs/docs/configuration/server.rst
@@ -217,6 +217,7 @@ for IPv4, ``/48`` for IPv6).
ratelimit = 2
direct-reply = 3
reply-to-self = false
+ require-author = false
require-email = false
enabled
@@ -237,6 +238,12 @@ reply-to-self
Do not forget to configure the client.
+require-author
+ force commenters to enter a value into the author field. No validation is
+ performed on the provided value.
+
+ Do not forget to configure the client accordingly.
+
require-email
force commenters to enter a value into the email field. No validation is
performed on the provided value.
diff --git a/isso/__init__.py b/isso/__init__.py
index ff8f6b4..7795c4f 100644
--- a/isso/__init__.py
+++ b/isso/__init__.py
@@ -194,7 +194,7 @@ def make_app(conf=None, threading=True, multiprocessing=False, uwsgi=False):
allowed=("Origin", "Referer", "Content-Type"),
exposed=("X-Set-Cookie", "Date")))
- wrapper.extend([wsgi.SubURI, ProxyFix, wsgi.LegacyWerkzeugMiddleware])
+ wrapper.extend([wsgi.SubURI, ProxyFix])
if werkzeug.version.startswith("0.8"):
wrapper.append(wsgi.LegacyWerkzeugMiddleware)
diff --git a/isso/css/isso.css b/isso/css/isso.css
index b0ed6d1..2d587ff 100644
--- a/isso/css/isso.css
+++ b/isso/css/isso.css
@@ -145,6 +145,9 @@
.isso-comment .isso-postbox {
margin-top: 0.8em;
}
+.isso-comment.isso-no-votes span.votes {
+ display: none;
+}
.isso-postbox {
max-width: 68em;
diff --git a/isso/db/spam.py b/isso/db/spam.py
index 8a1c747..d198f6a 100644
--- a/isso/db/spam.py
+++ b/isso/db/spam.py
@@ -66,6 +66,10 @@ class Guard:
if self.conf.getboolean("require-email") and not comment.get("email"):
return False, "email address required but not provided"
+ # require author if :param:`require-author` is enabled
+ if self.conf.getboolean("require-author") and not comment.get("author"):
+ return False, "author address required but not provided"
+
return True, ""
def _spam(self, uri, comment):
diff --git a/isso/js/app/config.js b/isso/js/app/config.js
index 35bf051..952d588 100644
--- a/isso/js/app/config.js
+++ b/isso/js/app/config.js
@@ -6,6 +6,7 @@ define(function() {
"lang": (navigator.language || navigator.userLanguage).split("-")[0],
"reply-to-self": false,
"require-email": false,
+ "require-author": false,
"max-comments-top": "inf",
"max-comments-nested": 5,
"reveal-on-click": 5,
@@ -13,7 +14,8 @@ define(function() {
"avatar-bg": "#f0f0f0",
"avatar-fg": ["#9abf88", "#5698c4", "#e279a3", "#9163b6",
"#be5168", "#f19670", "#e4bf80", "#447c69"].join(" "),
- "vote": true
+ "vote": true,
+ "vote-levels": null
};
var js = document.getElementsByTagName("script");
diff --git a/isso/js/app/dom.js b/isso/js/app/dom.js
index 9a50609..ec76e13 100644
--- a/isso/js/app/dom.js
+++ b/isso/js/app/dom.js
@@ -205,10 +205,13 @@ define(function() {
el.href = "#";
}
+ if (!content && content !== 0) {
+ content = "";
+ }
if (["TEXTAREA", "INPUT"].indexOf(el.nodeName) > -1) {
- el.value = content || "";
+ el.value = content;
} else {
- el.textContent = content || "";
+ el.textContent = content;
}
return el;
};
diff --git a/isso/js/app/globals.js b/isso/js/app/globals.js
index 6c411f1..680a96c 100644
--- a/isso/js/app/globals.js
+++ b/isso/js/app/globals.js
@@ -10,7 +10,7 @@ define(function() {
};
Offset.prototype.localTime = function() {
- return new Date((new Date()).getTime() + this.values.reduce(
+ return new Date((new Date()).getTime() - this.values.reduce(
function(a, b) { return a + b; }) / this.values.length);
};
@@ -18,4 +18,4 @@ define(function() {
offset: new Offset()
};
-}); \ No newline at end of file
+});
diff --git a/isso/js/app/i18n.js b/isso/js/app/i18n.js
index 2c1c756..2765915 100644
--- a/isso/js/app/i18n.js
+++ b/isso/js/app/i18n.js
@@ -1,19 +1,22 @@
-define(["app/config", "app/i18n/cs", "app/i18n/de", "app/i18n/en",
- "app/i18n/fr", "app/i18n/hr", "app/i18n/ru", "app/i18n/it",
- "app/i18n/eo", "app/i18n/sv", "app/i18n/nl", "app/i18n/el_GR",
- "app/i18n/es", "app/i18n/vi", "app/i18n/zh_CN"],
- function(config, cs, de, en, fr, hr, ru, it, eo, sv, nl, el, es, vi, zh) {
+define(["app/config", "app/i18n/bg", "app/i18n/cs", "app/i18n/de",
+ "app/i18n/en", "app/i18n/fi", "app/i18n/fr", "app/i18n/hr",
+ "app/i18n/ru", "app/i18n/it", "app/i18n/eo", "app/i18n/sv",
+ "app/i18n/nl", "app/i18n/el_GR", "app/i18n/es", "app/i18n/vi",
+ "app/i18n/zh_CN"],
+ function(config, bg, cs, de, en, fi, fr, hr, ru, it, eo, sv, nl, el, es, vi, zh) {
"use strict";
var pluralforms = function(lang) {
switch (lang) {
+ case "bg":
case "cs":
case "de":
case "el":
case "en":
case "es":
case "eo":
+ case "fi":
case "hr":
case "it":
case "sv":
@@ -57,6 +60,7 @@ define(["app/config", "app/i18n/cs", "app/i18n/de", "app/i18n/en",
en: en,
eo: eo,
es: es,
+ fi: fi,
fr: fr,
it: it,
hr: hr,
diff --git a/isso/js/app/i18n/fi.js b/isso/js/app/i18n/fi.js
new file mode 100644
index 0000000..80b6316
--- /dev/null
+++ b/isso/js/app/i18n/fi.js
@@ -0,0 +1,30 @@
+define({
+ "postbox-text": "Kirjoita kommentti tähän (vähintään 3 merkkiä)",
+ "postbox-author": "Nimi (valinnainen)",
+ "postbox-email": "Sähköposti (valinnainen)",
+ "postbox-website": "Web-sivu (valinnainen)",
+ "postbox-submit": "Lähetä",
+
+ "num-comments": "Yksi kommentti\n{{ n }} kommenttia",
+ "no-comments": "Ei vielä kommentteja",
+
+ "comment-reply": "Vastaa",
+ "comment-edit": "Muokkaa",
+ "comment-save": "Tallenna",
+ "comment-delete": "Poista",
+ "comment-confirm": "Vahvista",
+ "comment-close": "Sulje",
+ "comment-cancel": "Peru",
+ "comment-deleted": "Kommentti on poistettu.",
+ "comment-queued": "Kommentti on laitettu jonoon odottamaan moderointia.",
+ "comment-anonymous": "Nimetön",
+ "comment-hidden": "{{ n }} piilotettua",
+
+ "date-now": "hetki sitten",
+ "date-minute": "minuutti sitten\n{{ n }} minuuttia sitten",
+ "date-hour": "tunti sitten\n{{ n }} tuntia sitten",
+ "date-day": "eilen\n{{ n }} päivää sitten",
+ "date-week": "viime viikolla\n{{ n }} viikkoa sitten",
+ "date-month": "viime kuussa\n{{ n }} kuukautta sitten",
+ "date-year": "viime vuonna\n{{ n }} vuotta sitten"
+});
diff --git a/isso/js/app/i18n/zh_CN.js b/isso/js/app/i18n/zh_CN.js
index 70ae081..b9d4582 100644
--- a/isso/js/app/i18n/zh_CN.js
+++ b/isso/js/app/i18n/zh_CN.js
@@ -1,8 +1,8 @@
define({
- "postbox-text": "在此输入评论(最少3个字符)",
- "postbox-author": "名字(可选)",
- "postbox-email": "E-mail(可选)",
- "postbox-website": "网站(可选)",
+ "postbox-text": "在此输入评论 (最少3个字符)",
+ "postbox-author": "名字 (可选)",
+ "postbox-email": "E-mail (可选)",
+ "postbox-website": "网站 (可选)",
"postbox-submit": "提交",
"num-comments": "1条评论\n{{ n }}条评论",
diff --git a/isso/js/app/i18n/zh_TW.js b/isso/js/app/i18n/zh_TW.js
index 20191da..9bb59fa 100644
--- a/isso/js/app/i18n/zh_TW.js
+++ b/isso/js/app/i18n/zh_TW.js
@@ -1,8 +1,8 @@
define({
"postbox-text": "在此輸入留言(至少3個字元)",
- "postbox-author": "名稱(非必填)",
- "postbox-email": "電子信箱(非必填)",
- "postbox-website": "個人網站(非必填)",
+ "postbox-author": "名稱 (非必填)",
+ "postbox-email": "電子信箱 (非必填)",
+ "postbox-website": "個人網站 (非必填)",
"postbox-submit": "送出",
"num-comments": "1則留言\n{{ n }}則留言",
diff --git a/isso/js/app/isso.js b/isso/js/app/isso.js
index a46f43a..0523e9b 100644
--- a/isso/js/app/isso.js
+++ b/isso/js/app/isso.js
@@ -30,6 +30,12 @@ define(["app/dom", "app/utils", "app/config", "app/api", "app/jade", "app/i18n",
$("[name='email']", this).focus();
return false;
}
+ if (config["require-author"] &&
+ $("[name='author']", this).value.length <= 0)
+ {
+ $("[name='author']", this).focus();
+ return false;
+ }
return true;
};
@@ -39,6 +45,12 @@ define(["app/dom", "app/utils", "app/config", "app/api", "app/jade", "app/i18n",
$("[name='email']", el).placeholder.replace(/ \(.*\)/, "");
}
+ // author is not optional if this config parameter is set
+ if (config["require-author"]) {
+ $("[name='author']", el).placeholder =
+ $("[name='author']", el).placeholder.replace(/ \(.*\)/, "");
+ }
+
// submit form, initialize optional fields with `null` and reset form.
// If replied to a comment, remove form completely.
$("[type=submit]", el).on("click", function() {
@@ -57,7 +69,8 @@ define(["app/dom", "app/utils", "app/config", "app/api", "app/jade", "app/i18n",
api.create($("#isso-thread").getAttribute("data-isso-id"), {
author: author, email: email, website: website,
text: utils.text($(".textarea", el).innerHTML),
- parent: parent || null
+ parent: parent || null,
+ title: $("#isso-thread").getAttribute("data-title") || null
}).then(function(comment) {
$(".textarea", el).innerHTML = "";
$(".textarea", el).blur();
@@ -165,18 +178,34 @@ define(["app/dom", "app/utils", "app/config", "app/api", "app/jade", "app/i18n",
);
if (config.vote) {
- // update vote counter, but hide if votes sum to 0
+ var voteLevels = config['vote-levels'];
+ if (typeof voteLevels === 'string') {
+ // Eg. -5,5,15
+ voteLevels = voteLevels.split(',');
+ }
+
+ // update vote counter
var votes = function (value) {
var span = $("span.votes", footer);
if (span === null) {
- if (value !== 0) {
- footer.prepend($.new("span.votes", value));
- }
+ footer.prepend($.new("span.votes", value));
} else {
- if (value === 0) {
- span.remove();
- } else {
- span.textContent = value;
+ span.textContent = value;
+ }
+ if (value) {
+ el.classList.remove('isso-no-votes');
+ } else {
+ el.classList.add('isso-no-votes');
+ }
+ if (voteLevels) {
+ var before = true;
+ for (var index = 0; index <= voteLevels.length; index++) {
+ if (before && (index >= voteLevels.length || value < voteLevels[index])) {
+ el.classList.add('isso-vote-level-' + index);
+ before = false;
+ } else {
+ el.classList.remove('isso-vote-level-' + index);
+ }
}
}
};
@@ -192,6 +221,8 @@ define(["app/dom", "app/utils", "app/config", "app/api", "app/jade", "app/i18n",
votes(rv.likes - rv.dislikes);
});
});
+
+ votes(comment.likes - comment.dislikes);
}
$("a.edit", footer).toggle("click",
diff --git a/isso/js/app/text/comment.jade b/isso/js/app/text/comment.jade
index 95dc7b1..4884bf7 100644
--- a/isso/js/app/text/comment.jade
+++ b/isso/js/app/text/comment.jade
@@ -24,8 +24,6 @@ div(class='isso-comment' id='isso-#{comment.id}')
div(class='isso-comment-footer')
if conf.vote
- if comment.likes - comment.dislikes != 0
- span(class='votes') #{comment.likes - comment.dislikes}
a(class='upvote' href='#')
!= svg['arrow-up']
span(class='spacer') |
diff --git a/isso/tests/test_comments.py b/isso/tests/test_comments.py
index 70bd3a3..1e2bdf1 100644
--- a/isso/tests/test_comments.py
+++ b/isso/tests/test_comments.py
@@ -375,6 +375,14 @@ class TestComments(unittest.TestCase):
# just for the record
self.assertEqual(self.post('/id/1/dislike', content_type=js).status_code, 200)
+ def testPreview(self):
+ response = self.post('/preview', data=json.dumps({'text': 'This is **mark***down*'}))
+ self.assertEqual(response.status_code, 200)
+
+ rv = loads(response.data)
+ self.assertEqual(rv["text"], '<p>This is <strong>mark</strong><em>down</em></p>')
+
+
class TestModeratedComments(unittest.TestCase):
diff --git a/isso/tests/test_guard.py b/isso/tests/test_guard.py
index 8a050d9..fca932c 100644
--- a/isso/tests/test_guard.py
+++ b/isso/tests/test_guard.py
@@ -35,7 +35,8 @@ class TestGuard(unittest.TestCase):
def setUp(self):
self.path = tempfile.NamedTemporaryFile().name
- def makeClient(self, ip, ratelimit=2, direct_reply=3, self_reply=False, require_email=False):
+ def makeClient(self, ip, ratelimit=2, direct_reply=3, self_reply=False,
+ require_email=False, require_author=False):
conf = config.load(os.path.join(dist.location, "share", "isso.conf"))
conf.set("general", "dbpath", self.path)
@@ -45,6 +46,7 @@ class TestGuard(unittest.TestCase):
conf.set("guard", "direct-reply", str(direct_reply))
conf.set("guard", "reply-to-self", "1" if self_reply else "0")
conf.set("guard", "require-email", "1" if require_email else "0")
+ conf.set("guard", "require-author", "1" if require_author else "0")
class App(Isso, core.Mixin):
pass
@@ -120,8 +122,8 @@ class TestGuard(unittest.TestCase):
payload = lambda email: json.dumps({"text": "...", "email": email})
- client = self.makeClient("127.0.0.1", ratelimit=4, require_email=False)
- client_strict = self.makeClient("127.0.0.2", ratelimit=4, require_email=True)
+ client = self.makeClient("127.0.0.1", ratelimit=4, require_email=False)
+ client_strict = self.makeClient("127.0.0.2", ratelimit=4, require_email=True)
# if we don't require email
self.assertEqual(client.post("/new?uri=test", data=payload("")).status_code, 201)
@@ -130,3 +132,18 @@ class TestGuard(unittest.TestCase):
# if we do require email
self.assertEqual(client_strict.post("/new?uri=test", data=payload("")).status_code, 403)
self.assertEqual(client_strict.post("/new?uri=test", data=payload("test@me.more")).status_code, 201)
+
+ def testRequireAuthor(self):
+
+ payload = lambda author: json.dumps({"text": "...", "author": author})
+
+ client = self.makeClient("127.0.0.1", ratelimit=4, require_author=False)
+ client_strict = self.makeClient("127.0.0.2", ratelimit=4, require_author=True)
+
+ # if we don't require author
+ self.assertEqual(client.post("/new?uri=test", data=payload("")).status_code, 201)
+ self.assertEqual(client.post("/new?uri=test", data=payload("pipo author")).status_code, 201)
+
+ # if we do require author
+ self.assertEqual(client_strict.post("/new?uri=test", data=payload("")).status_code, 403)
+ self.assertEqual(client_strict.post("/new?uri=test", data=payload("pipo author")).status_code, 201)
diff --git a/isso/views/comments.py b/isso/views/comments.py
index 0272fa3..d328305 100644
--- a/isso/views/comments.py
+++ b/isso/views/comments.py
@@ -75,7 +75,7 @@ class API(object):
'mode', 'created', 'modified', 'likes', 'dislikes', 'hash'])
# comment fields, that can be submitted
- ACCEPT = set(['text', 'author', 'website', 'email', 'parent'])
+ ACCEPT = set(['text', 'author', 'website', 'email', 'parent', 'title'])
VIEWS = [
('fetch', ('GET', '/')),
@@ -89,7 +89,8 @@ class API(object):
('moderate',('POST', '/id/<int:id>/<any(activate,delete):action>/<string:key>')),
('like', ('POST', '/id/<int:id>/like')),
('dislike', ('POST', '/id/<int:id>/dislike')),
- ('demo', ('GET', '/demo'))
+ ('demo', ('GET', '/demo')),
+ ('preview', ('POST', '/preview'))
]
def __init__(self, isso, hasher):
@@ -168,11 +169,14 @@ class API(object):
with self.isso.lock:
if uri not in self.threads:
- with http.curl('GET', local("origin"), uri) as resp:
- if resp and resp.status == 200:
- uri, title = parse.thread(resp.read(), id=uri)
- else:
- return NotFound('URI does not exist')
+ if 'title' not in data:
+ with http.curl('GET', local("origin"), uri) as resp:
+ if resp and resp.status == 200:
+ uri, title = parse.thread(resp.read(), id=uri)
+ else:
+ return NotFound('URI does not exist %s')
+ else:
+ title = data['title']
thread = self.threads.new(uri, title)
self.signal("comments.new:new-thread", thread)
@@ -476,5 +480,13 @@ class API(object):
return JSON(self.comments.count(*data), 200)
+ def preview(self, environment, request):
+ data = request.get_json()
+
+ if "text" not in data or data["text"] is None:
+ raise BadRequest("no text given")
+
+ return JSON({'text': self.isso.render(data["text"])}, 200)
+
def demo(self, env, req):
return redirect(get_current_url(env) + '/index.html')
diff --git a/setup.py b/setup.py
index b9a47d7..793ede2 100644
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@ if (3, 0) <= sys.version_info < (3, 3):
setup(
name='isso',
- version='0.10.4',
+ version='0.10.6',
author='Martin Zimmermann',
author_email='info@posativ.org',
packages=find_packages(),
diff --git a/share/isso.conf b/share/isso.conf
index be17a50..e17de4f 100644
--- a/share/isso.conf
+++ b/share/isso.conf
@@ -130,6 +130,11 @@ direct-reply = 3
# their own comments anyways. Do not forget to configure the client.
reply-to-self = false
+# force commenters to enter a value into the author field. No validation is
+# performed on the provided value. Do not forget to configure the client
+# accordingly.
+require-author = false
+
# require the commenter to enter an email address (note: no validation is
# done on the provided address). Do not forget to configure the client.
require-email = false