summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorByron <byroncorrales@gmail.com>2011-09-27 14:53:50 -0600
committerByron <byroncorrales@gmail.com>2011-09-27 14:53:50 -0600
commit640ccca72ee78dd9876e235d930b7ee393f42017 (patch)
tree9ae7470e5f6f5946bf7f8b9832e2c856622668e5
parent8b0363c4b3613415bb887f25bfdf1b540208a222 (diff)
parentb208c5648d4fbf810b65283db4a6eae151839570 (diff)
downloadaskbot-640ccca72ee78dd9876e235d930b7ee393f42017.tar.gz
askbot-640ccca72ee78dd9876e235d930b7ee393f42017.tar.bz2
askbot-640ccca72ee78dd9876e235d930b7ee393f42017.zip
Merge branch 'master' of https://github.com/ASKBOT/askbot-devel
-rw-r--r--askbot/__init__.py2
-rw-r--r--askbot/conf/markup.py80
-rw-r--r--askbot/doc/source/changelog.rst13
-rw-r--r--askbot/doc/source/contributors.rst1
-rw-r--r--askbot/skins/default/templates/user_profile/user_moderate.html28
-rw-r--r--askbot/utils/markup.py67
6 files changed, 174 insertions, 17 deletions
diff --git a/askbot/__init__.py b/askbot/__init__.py
index 8133c74f..5ced4ca1 100644
--- a/askbot/__init__.py
+++ b/askbot/__init__.py
@@ -9,7 +9,7 @@ import smtplib
import sys
import logging
-VERSION = (0, 7, 22)
+VERSION = (0, 7, 23)
#necessary for interoperability of django and coffin
try:
diff --git a/askbot/conf/markup.py b/askbot/conf/markup.py
index 026c5536..e4202f05 100644
--- a/askbot/conf/markup.py
+++ b/askbot/conf/markup.py
@@ -4,17 +4,34 @@ Settings that modify processing of user text input
from askbot.conf.settings_wrapper import settings
from askbot.deps.livesettings import ConfigurationGroup
-from askbot.deps.livesettings import BooleanValue, StringValue
+from askbot.deps.livesettings import BooleanValue, StringValue, LongStringValue
from django.utils.translation import ugettext as _
-import askbot
from askbot import const
-import os
+import re
MARKUP = ConfigurationGroup(
'MARKUP',
_('Markup formatting')
)
+def regex_settings_validation(*args):
+ """
+ Validate the regular expressions
+ """
+ try:
+
+ new_value = args[1]
+ regex_list = new_value.split('\n')
+
+ for i in range(0, len(regex_list)):
+ re.compile(regex_list[i].strip())
+ return args[1]
+
+ except Exception:
+ # The regex is invalid, so we overwrite it with empty string
+ return ""
+
+
settings.register(
BooleanValue(
MARKUP,
@@ -63,3 +80,60 @@ settings.register(
default = ''
)
)
+
+
+settings.register(
+ BooleanValue(
+ MARKUP,
+ 'ENABLE_AUTO_LINKING',
+ description=_('Enable autolinking with specific patterns'),
+ help_text=_(
+ 'If you enable this feature, '
+ 'the application will be able to '
+ 'detect patterns and auto link to URLs'
+ ),
+ default = False
+ )
+)
+
+
+settings.register(
+ LongStringValue(
+ MARKUP,
+ 'AUTO_LINK_PATTERNS',
+ description=_('Regexes to detect the link patterns'),
+ help_text=_(
+ 'Enter valid regular expressions for the patters,'
+ ' one per line.'
+ ' For example to'
+ ' detect a bug pattern like #bug123,'
+ ' use the following regex: #bug(\d+). The numbers'
+ ' captured by the pattern in the parentheses will'
+ ' be transferred to the link url template.'
+ ' Please look up more information about regular'
+ ' expressions elsewhere.'
+ ),
+ update_callback=regex_settings_validation,
+ default = ''
+ )
+ )
+
+settings.register(
+ LongStringValue(
+ MARKUP,
+ 'AUTO_LINK_URLS',
+ description=_('URLs for autolinking'),
+ help_text=_(
+ 'Here, please enter url templates for the patterns'
+ ' entered in the previous setting, also one entry per line.'
+ ' <strong>Make sure that number of lines in this setting'
+ ' and the previous one are the same</strong>'
+ ' For example template'
+ ' https://bugzilla.redhat.com/show_bug.cgi?id=\\1'
+ ' together with the pattern shown above'
+ ' and the entry in the post #123'
+ ' will produce link to the bug 123 in the redhat bug tracker.'
+ ),
+ default = ''
+ )
+)
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
index c40f08c1..33a0199c 100644
--- a/askbot/doc/source/changelog.rst
+++ b/askbot/doc/source/changelog.rst
@@ -1,8 +1,13 @@
Changes in Askbot
=================
-Development version
--------------------
+Development version (not released yet)
+--------------------------------------
+* Added annotations for the meanings of user levels on the "moderation" page. (Jishnu)
+* Auto-link patterns - e.g. to bug databases - are configurable from settings. (Arun SAG)
+
+0.7.23 (Current Version)
+------------------------
* Greeting for anonymuos users can be changed from live settings (Hrishi)
* Greeting for anonymous users is shown only once (Rag Sagar)
* Added support for Akismet spam detection service (Adolfo Fitoria)
@@ -11,8 +16,8 @@ Development version
* Allowed logging in with password and email in the place of login name (Evgeny)
* Added config settings allowing adjust license information (Evgeny)
-0.7.22 (Current Version)
-------------------------
+0.7.22
+------
* Media resource revision is now incremented
automatically any time when media is updated (Adolfo Fitoria, Evgeny Fadeev)
* First user automatically becomes site administrator (Adolfo Fitoria)
diff --git a/askbot/doc/source/contributors.rst b/askbot/doc/source/contributors.rst
index 35c02be1..fb8d9690 100644
--- a/askbot/doc/source/contributors.rst
+++ b/askbot/doc/source/contributors.rst
@@ -15,6 +15,7 @@ Programming and documentation
* Andy Knotts
* Benoit Lavine (with Windriver Software, Inc.)
* Jeff Madynski
+* `Jishnu <http://thecodecracker.com/>`_
* `Hrishi <https://github.com/stultus>`_
* Andrei Mamoutkine
* Ramiro Morales (with Machinalis)
diff --git a/askbot/skins/default/templates/user_profile/user_moderate.html b/askbot/skins/default/templates/user_profile/user_moderate.html
index 563026a4..b2f350df 100644
--- a/askbot/skins/default/templates/user_profile/user_moderate.html
+++ b/askbot/skins/default/templates/user_profile/user_moderate.html
@@ -15,6 +15,8 @@
<table class="form-as-table">
{{ change_user_status_form.as_table() }}
</table>
+ <p id="id_user_status_info">
+ </p>
<input type="submit" class="submit" name="change_status" value="{% trans %}Save{% endtrans %}" />
</form>
{% endif %}
@@ -64,3 +66,29 @@
</form>
{% endif %}
{% endblock %}
+{% block endjs %}
+ <script type="text/javascript" >
+ $("#id_user_status_info").hide();
+ $("#id_user_status").change(function () {
+ var optionValue = $(this).attr('value');
+ if (optionValue == "d") {
+ $('#id_user_status_info').html("{% trans %}Administrators have privileges of normal users, but in addition they can assign/revoke any status to any user, and are exempt from the reputation limits.{% endtrans %}");
+ $('#id_user_status_info').show('slow');
+ } else if (optionValue == "m"){
+ $('#id_user_status_info').html("{% trans %}Moderators have the same privileges as administrators, but cannot add or remove user status of 'moderator' or 'administrator'.{% endtrans %}");
+ $('#id_user_status_info').show('slow');
+ } else if (optionValue == "a"){
+ $('#id_user_status_info').html("{% trans %}'Approved' status means the same as regular user.{% endtrans %}");
+ $('#id_user_status_info').show('slow');
+ } else if (optionValue == "s"){
+ $('#id_user_status_info').html("{% trans %}Suspended users can only edit or delete their own posts.{% endtrans %}");
+ $('#id_user_status_info').show('slow');
+ } else if (optionValue == "b"){
+ $('#id_user_status_info').html("{% trans %}Blocked users can only login and send feedback to the site administrators.{% endtrans %}");
+ $('#id_user_status_info').show('slow');
+ } else {
+ $('#id_user_status_info').hide('slow');
+ }
+ })
+ </script>
+{% endblock %}
diff --git a/askbot/utils/markup.py b/askbot/utils/markup.py
index acb8d03d..60bde9a0 100644
--- a/askbot/utils/markup.py
+++ b/askbot/utils/markup.py
@@ -1,8 +1,13 @@
+"""methods that make parsing of post inputs possible,
+handling of markdown and additional syntax rules -
+such as optional link patterns, video embedding and
+Twitter-style @mentions"""
+
import re
+import logging
from askbot import const
from askbot.conf import settings as askbot_settings
from markdown2 import Markdown
-
#url taken from http://regexlib.com/REDetails.aspx?regexp_id=501 by Brian Bothwell
URL_RE = re.compile("((?<!(href|.src|data)=['\"])((http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&amp;%\$#\=~_\-]+))*))")
@@ -10,7 +15,10 @@ LINK_PATTERNS = [
(URL_RE, r'\1'),
]
+
def get_parser():
+ """returns an instance of configured ``markdown2`` parser
+ """
extras = ['link-patterns', 'video']
if askbot_settings.ENABLE_MATHJAX or \
askbot_settings.MARKUP_CODE_FRIENDLY:
@@ -22,6 +30,30 @@ def get_parser():
#pip install -e git+git://github.com/andryuha/python-markdown2.git
extras.append('video')
+ if askbot_settings.ENABLE_AUTO_LINKING:
+ pattern_list = askbot_settings.AUTO_LINK_PATTERNS.split('\n')
+ url_list = askbot_settings.AUTO_LINK_URLS.split('\n')
+ pairs = zip(pattern_list, url_list)#always takes equal number of items
+ for item in pairs:
+ LINK_PATTERNS.append(
+ (
+ re.compile(item[0]),
+ item[1].strip()
+ )
+ )
+
+ #Check whether we have matching links for all key terms,
+ #Other wise we ignore the key terms
+ #May be we should do this test in update_callback?
+ #looks like this might be a defect of livesettings
+ #as there seems to be no way
+ #to validate entries that depend on each other
+ if len(pattern_list) != len(url_list):
+ settings_url = askbot_settings.APP_URL+'/settings/AUTOLINK/'
+ logging.critical(
+ "Number of autolink patterns didn't match the number "
+ "of url templates, fix this by visiting" + settings_url)
+
return Markdown(
html4tags=True,
extras=extras,
@@ -30,18 +62,23 @@ def get_parser():
def format_mention_in_html(mentioned_user):
+ """formats mention as url to the user profile"""
url = mentioned_user.get_profile_url()
username = mentioned_user.username
return '<a href="%s">@%s</a>' % (url, username)
def extract_first_matching_mentioned_author(text, anticipated_authors):
+ """matches beginning of ``text`` string with the names
+ of ``anticipated_authors`` - list of user objects.
+ Returns upon first match the first matched user object
+ and the remainder of the ``text`` that is left unmatched"""
if len(text) == 0:
return None, ''
- for a in anticipated_authors:
- if text.lower().startswith(a.username.lower()):
- ulen = len(a.username)
+ for author in anticipated_authors:
+ if text.lower().startswith(author.username.lower()):
+ ulen = len(author.username)
if len(text) == ulen:
text = ''
elif text[ulen] in const.TWITTER_STYLE_MENTION_TERMINATION_CHARS:
@@ -50,17 +87,24 @@ def extract_first_matching_mentioned_author(text, anticipated_authors):
#near miss, here we could insert a warning that perhaps
#a termination character is needed
continue
- return a, text
+ return author, text
return None, text
def extract_mentioned_name_seeds(text):
+ """Returns list of strings that
+ follow the '@' symbols in the text.
+ The strings will be 10 characters long,
+ or shorter, if the subsequent character
+ is one of the list accepted to be termination
+ characters.
+ """
extra_name_seeds = set()
while '@' in text:
pos = text.index('@')
text = text[pos+1:]#chop off prefix
name_seed = ''
- for c in text:
- if c in const.TWITTER_STYLE_MENTION_TERMINATION_CHARS:
+ for char in text:
+ if char in const.TWITTER_STYLE_MENTION_TERMINATION_CHARS:
extra_name_seeds.add(name_seed)
name_seed = ''
break
@@ -68,12 +112,12 @@ def extract_mentioned_name_seeds(text):
extra_name_seeds.add(name_seed)
name_seed = ''
break
- if c == '@':
+ if char == '@':
if len(name_seed) > 0:
extra_name_seeds.add(name_seed)
name_seed = ''
break
- name_seed += c
+ name_seed += char
if len(name_seed) > 0:
#in case we run off the end of text
extra_name_seeds.add(name_seed)
@@ -81,6 +125,11 @@ def extract_mentioned_name_seeds(text):
return extra_name_seeds
def mentionize_text(text, anticipated_authors):
+ """Returns a tuple of two items:
+ * modified text where @mentions are
+ replaced with urls to the corresponding user profiles
+ * list of users whose names matched the @mentions
+ """
output = ''
mentioned_authors = list()
while '@' in text: