New help system and footer

This commit is contained in:
Mike
2009-05-06 15:39:16 -07:00
parent 09045d987d
commit 2de837f52a
15 changed files with 313 additions and 211 deletions

View File

@@ -115,6 +115,8 @@ MIN_DOWN_KARMA = 0
MIN_RATE_LIMIT_KARMA = 0
MIN_RATE_LIMIT_COMMENT_KARMA = 0
WIKI_KARMA = 50
# time in days
MODWINDOW = 2
HOT_PAGE_AGE = 1

View File

@@ -20,12 +20,15 @@
# CondeNet, Inc. All Rights Reserved.
################################################################################
from reddit_base import RedditController, proxyurl
from pylons import request
from r2.lib.pages import Embed, BoringPage
from r2.lib.pages import Embed, BoringPage, HelpPage
from r2.lib.filters import websafe, SC_OFF, SC_ON
from pylons.i18n import _
from urllib2 import HTTPError
from pylons import request
from pylons import c
from BeautifulSoup import BeautifulSoup, Tag
from urllib2 import HTTPError
def force_redirect(dest):
def _force_redirect(self, *a, **kw):
@@ -33,27 +36,51 @@ def force_redirect(dest):
return _force_redirect
class EmbedController(RedditController):
def rendercontent(self, input, fp):
soup = BeautifulSoup(input)
def rendercontent(self, content):
if content.startswith("<!--TEMPLATE-->"):
return BoringPage(_("help"),
content = Embed(content=content),
show_sidebar = None,
space_compress = False).render()
else:
return content
output = soup.find("div", { 'class':'wiki', 'id':'content'} )
# Replace all links to "/wiki/help/..." with "/help/..."
for link in output.findAll('a'):
if link.has_key('href') and link['href'].startswith("/wiki/help"):
link['href'] = link['href'][5:]
# Add "edit this page" link if the user is allowed to edit the wiki
if c.user_is_loggedin and c.user.can_wiki():
edit_text = _('edit this page')
read_first = _('read this first')
url = "http://code.reddit.com/wiki" + websafe(fp) + "?action=edit"
edittag = """
<div class="editlink">
<hr/>
<a href="%s">%s</a>&#32;
(<a href="/help/editing_help">%s</a>)
</div>
""" % (url, edit_text, read_first)
output.append(edittag)
output = SC_OFF + unicode(output) + SC_ON
return HelpPage(_("help"),
content = Embed(content=output),
show_sidebar = None).render()
def renderurl(self):
# Needed so http://reddit.com/help/ works
fp = request.path.rstrip("/")
u = "http://code.reddit.com/wiki" + fp + '?stripped=1'
try:
content = proxyurl("http://reddit.infogami.com"+request.fullpath)
return self.rendercontent(content)
content = proxyurl(u)
return self.rendercontent(content, fp)
except HTTPError, e:
if e.code == 404:
return self.abort404()
else:
if e.code != 404:
print "error %s" % e.code
print e.fp.read()
return self.abort404()
GET_help = POST_help = renderurl
GET_blog = force_redirect("http://blog.reddit.com/")

View File

@@ -465,7 +465,8 @@ class FrontController(RedditController):
returns their user name"""
c.response_content_type = 'text/plain'
if c.user_is_loggedin:
c.response.content = c.user.name
perm = str(c.user.can_wiki())
c.response.content = c.user.name + "," + perm
else:
c.response.content = ''
return c.response

View File

@@ -38,6 +38,7 @@ class Globals(object):
'MIN_DOWN_KARMA',
'MIN_RATE_LIMIT_KARMA',
'MIN_RATE_LIMIT_COMMENT_KARMA',
'WIKI_KARMA',
'HOT_PAGE_AGE',
'MODWINDOW',
'RATELIMIT',

View File

@@ -26,10 +26,13 @@ from pylons.i18n import N_, _, ungettext, get_lang
import r2.lib.helpers as h
from r2.lib.utils import to_js
from r2.lib.filters import spaceCompress, _force_unicode
from r2.lib.template_helpers import get_domain
from utils import storify, string2js, read_http_date
import re, md5
from urllib import quote
import urllib2
#TODO hack
import logging
@@ -159,21 +162,14 @@ class BaseController(WSGIController):
c.response.content = to_js(js, callback, escape)
return c.response
import urllib2
class EmbedHandler(urllib2.BaseHandler, urllib2.HTTPHandler,
class EmbedHandler(urllib2.BaseHandler, urllib2.HTTPHandler,
urllib2.HTTPErrorProcessor, urllib2.HTTPDefaultErrorHandler):
@staticmethod
def redirect(_status):
def _redirect(url, status = None):
MethodController.redirect(url, code = _status)
return _redirect
def http_redirect(self, req, fp, code, msg, hdrs):
codes = [301, 302, 303, 307]
map = dict((x, self.redirect(x)) for x in codes)
to = hdrs['Location'].replace('reddit.infogami.com', g.domain)
map[code](to)
raise StopIteration
to = hdrs['Location']
h = urllib2.HTTPRedirectHandler()
r = h.redirect_request(req, fp, code, msg, hdrs, to)
return embedopen.open(r)
http_error_301 = http_redirect
http_error_302 = http_redirect
@@ -184,17 +180,7 @@ embedopen = urllib2.OpenerDirector()
embedopen.add_handler(EmbedHandler())
def proxyurl(url):
cstrs = ['%s="%s"' % (k, v.value) for k, v in c.cookies.iteritems()]
cookiestr = "; ".join(cstrs)
headers = {"Cookie":cookiestr}
# TODO make this work on POST
data = None
r = urllib2.Request(url, data, headers)
r = urllib2.Request(url, None, {})
content = embedopen.open(r).read()
return content
__all__ = [__name for __name in locals().keys() if not __name.startswith('_') \
or __name == '_']

View File

@@ -42,19 +42,19 @@ static PyObject *
filters_uwebsafe(PyObject * self, PyObject *args)
{
PyObject * com;
Py_UNICODE * command;
Py_UNICODE * input_buffer;
Py_UNICODE *buffer;
PyObject * res;
int ic=0, ib=0;
int len;
Py_UNICODE c;
if (!(com = unicode_arg(args))) return NULL;
command = PyUnicode_AS_UNICODE(com);
input_buffer = PyUnicode_AS_UNICODE(com);
len = PyUnicode_GetSize(com);
buffer = (Py_UNICODE*)malloc(6*len*sizeof(Py_UNICODE));
for(ic = 0, ib = 0; ic < len; ic++, ib++) {
c = command[ic];
c = input_buffer[ic];
if (c == '&') {
buffer[ib++] = (Py_UNICODE)'&';
buffer[ib++] = (Py_UNICODE)'a';
@@ -83,7 +83,7 @@ filters_uwebsafe(PyObject * self, PyObject *args)
buffer[ib] = (Py_UNICODE)';';
}
else {
buffer[ib] = command[ic];
buffer[ib] = input_buffer[ic];
}
}
res = PyUnicode_FromUnicode(buffer, ib);
@@ -96,19 +96,19 @@ static PyObject *
filters_uwebsafe_json(PyObject * self, PyObject *args)
{
PyObject * com;
Py_UNICODE * command;
Py_UNICODE * input_buffer;
Py_UNICODE *buffer;
PyObject * res;
int ic=0, ib=0;
int len;
Py_UNICODE c;
if (!(com = unicode_arg(args))) return NULL;
command = PyUnicode_AS_UNICODE(com);
input_buffer = PyUnicode_AS_UNICODE(com);
len = PyUnicode_GetSize(com);
buffer = (Py_UNICODE*)malloc(5*len*sizeof(Py_UNICODE));
for(ic = 0, ib = 0; ic < len; ic++, ib++) {
c = command[ic];
c = input_buffer[ic];
if (c == '&') {
buffer[ib++] = (Py_UNICODE)'&';
buffer[ib++] = (Py_UNICODE)'a';
@@ -129,7 +129,7 @@ filters_uwebsafe_json(PyObject * self, PyObject *args)
buffer[ib] = (Py_UNICODE)';';
}
else {
buffer[ib] = command[ic];
buffer[ib] = input_buffer[ic];
}
}
res = PyUnicode_FromUnicode(buffer, ib);
@@ -142,18 +142,18 @@ filters_uwebsafe_json(PyObject * self, PyObject *args)
static PyObject *
filters_websafe(PyObject * self, PyObject *args)
{
const char * command;
const char * input_buffer;
char *buffer;
PyObject * res;
int ic=0, ib=0;
int len;
char c;
if (!PyArg_ParseTuple(args, "s", &command))
if (!PyArg_ParseTuple(args, "s", &input_buffer))
return NULL;
len = strlen(command);
len = strlen(input_buffer);
buffer = (char*)malloc(5*len);
for(ic = 0, ib = 0; ic <= len; ic++, ib++) {
c = command[ic];
c = input_buffer[ic];
if (c == '&') {
buffer[ib++] = '&';
buffer[ib++] = 'a';
@@ -182,7 +182,7 @@ filters_websafe(PyObject * self, PyObject *args)
buffer[ib] = ';';
}
else {
buffer[ib] = command[ic];
buffer[ib] = input_buffer[ic];
}
}
res = Py_BuildValue("s", buffer);
@@ -199,12 +199,12 @@ void print_unicode(Py_UNICODE *c, int len) {
printf("\n");
}
const char *MD_START = "<div class=\"md\">";
const char *MD_END = "</div>";
const Py_UNICODE *MD_START_U;
const Py_UNICODE *MD_END_U;
int MD_START_LEN = 0;
int MD_END_LEN = 0;
const char *SC_OFF = "<!-- SC_OFF -->";
const char *SC_ON = "<!-- SC_ON -->";
const Py_UNICODE *SC_OFF_U;
const Py_UNICODE *SC_ON_U;
int SC_OFF_LEN = 0;
int SC_ON_LEN = 0;
@@ -218,7 +218,7 @@ filters_uspace_compress(PyObject * self, PyObject *args) {
PyObject * com;
PyObject * res;
Py_ssize_t len;
Py_UNICODE *command;
Py_UNICODE *input_buffer;
Py_UNICODE *buffer;
Py_UNICODE c;
int ic, ib;
@@ -227,36 +227,48 @@ filters_uspace_compress(PyObject * self, PyObject *args) {
if(!com) {
return NULL;
}
command = PyUnicode_AS_UNICODE(com);
input_buffer = PyUnicode_AS_UNICODE(com);
len = PyUnicode_GetSize(com);
buffer = (Py_UNICODE*)malloc(len * sizeof(Py_UNICODE));
/* ic -> input buffer index, ib -> output buffer */
for(ic = 0, ib = 0; ic <= len; ic++) {
c = command[ic];
c = input_buffer[ic];
/* gobble -> we are space compressing */
if(gobble) {
/* remove spaces if encountered */
if(Py_UNICODE_ISSPACE(c)) {
while(Py_UNICODE_ISSPACE(c)) { c = command[++ic]; }
/* after this loop, c will be a non-space */
while(Py_UNICODE_ISSPACE(c)) { c = input_buffer[++ic]; }
/* unless next char is a <, add a single space to account for
the multiple spaces that have been removed */
if(c != (Py_UNICODE)('<')) {
buffer[ib++] = (Py_UNICODE)(' ');
}
}
/* gobble all space after '>' */
if(c == (Py_UNICODE)('>')) {
buffer[ib++] = c;
c = command[++ic];
while(Py_UNICODE_ISSPACE(c)) { c = command[++ic]; }
c = input_buffer[++ic];
while(Py_UNICODE_ISSPACE(c)) { c = input_buffer[++ic]; }
}
if (len - ic >= MD_START_LEN &&
memcmp(&command[ic], MD_START_U,
sizeof(Py_UNICODE)*MD_START_LEN) == 0) {
/* does the next part of the string match the SC_OFF label */
if (len - ic >= SC_OFF_LEN &&
memcmp(&input_buffer[ic], SC_OFF_U,
sizeof(Py_UNICODE)*SC_OFF_LEN) == 0) {
/* disable gobbling, and bypass that part of the string */
gobble = 0;
ic += SC_OFF_LEN;
c = input_buffer[ic];
}
}
else {
if (len - ic > MD_END_LEN &&
memcmp(&command[ic], MD_END_U,
sizeof(Py_UNICODE)*MD_END_LEN) == 0) {
/* not gobbling, but find the SC_ON tag */
else if (len - ic >= SC_ON_LEN &&
memcmp(&input_buffer[ic], SC_ON_U,
sizeof(Py_UNICODE)*SC_ON_LEN) == 0) {
gobble = 1;
}
ic += SC_ON_LEN;
c = input_buffer[ic];
}
if(c) {
buffer[ib++] = c;
@@ -268,57 +280,6 @@ filters_uspace_compress(PyObject * self, PyObject *args) {
return res;
}
static PyObject *
filters_space_compress(PyObject * self, PyObject *args)
{
PyObject * res;
const char * command;
int len, ic, ib;
char c;
char * buffer;
int gobble = 1;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
len = strlen(command);
buffer = (char*)malloc(len);
for(ic = 0, ib = 0; ic <= len; ic++) {
c = command[ic];
if(gobble) {
if(c == '>') {
buffer[ib++] = c;
while(whitespace(command[++ic]));
c = command[ic];
}
else if(whitespace(c)) {
while(whitespace(command[++ic]));
c = command[ic];
if(c != '<') {
buffer[ib++] = ' ';
}
}
if (len - ic >= MD_START_LEN &&
strncmp(&command[ic], MD_START, MD_START_LEN) == 0) {
gobble = 0;
}
}
else {
if (len - ic > MD_END_LEN &&
strncmp(&command[ic], MD_END, MD_END_LEN) == 0) {
gobble = 1;
}
}
buffer[ib++] = c;
}
res = Py_BuildValue("s", buffer);
free(buffer);
return res;
}
static PyMethodDef FilterMethods[] = {
{"websafe", filters_websafe, METH_VARARGS,
"make string web safe."},
@@ -326,10 +287,8 @@ static PyMethodDef FilterMethods[] = {
"make string web safe."},
{"uwebsafe_json", filters_uwebsafe_json, METH_VARARGS,
"make string web safe, no &quot;."},
{"space_compress", filters_space_compress, METH_VARARGS,
"returns meep"},
{"uspace_compress", filters_uspace_compress, METH_VARARGS,
"returns meep"},
"removes spaces around angle brackets. Can be disabled with the use of SC_OFF and SC_ON comments from r2.lib.filters."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
@@ -347,10 +306,10 @@ Py_UNICODE *to_unicode(const char *c, int len) {
PyMODINIT_FUNC
initCfilters(void)
{
MD_START_LEN = strlen(MD_START);
MD_START_U = to_unicode(MD_START, MD_START_LEN);
MD_END_LEN = strlen(MD_END);
MD_END_U = to_unicode(MD_END, MD_END_LEN);
SC_OFF_LEN = strlen(SC_OFF);
SC_OFF_U = to_unicode(SC_OFF, SC_OFF_LEN);
SC_ON_LEN = strlen(SC_ON);
SC_ON_U = to_unicode(SC_ON, SC_ON_LEN);
(void) Py_InitModule("Cfilters", FilterMethods);
}

View File

@@ -25,8 +25,9 @@ import cgi
import urllib
import re
MD_START = '<div class="md">'
MD_END = '</div>'
SC_OFF = "<!-- SC_OFF -->"
SC_ON = "<!-- SC_ON -->"
def python_websafe(text):
@@ -50,15 +51,23 @@ except ImportError:
_between_tags1 = re.compile('> +')
_between_tags2 = re.compile(' +<')
_spaces = re.compile('[\s]+')
_ignore = re.compile('(' + MD_START + '.*?' + MD_END + ')', re.S | re.I)
_ignore = re.compile('(' + SC_OFF + '|' + SC_ON + ')', re.S | re.I)
def spaceCompress(content):
res = ''
sc = True
for p in _ignore.split(content):
if not p.startswith(MD_START) and not p.endswith(MD_END):
if p == SC_ON:
sc = True
elif p == SC_OFF:
sc = False
elif sc:
p = _spaces.sub(' ', p)
p = _between_tags1.sub('>', p)
p = _between_tags2.sub('<', p)
res += p
res += p
else:
res += p
return res
class _Unsafe(unicode): pass
@@ -141,7 +150,7 @@ def safemarkdown(text, nofollow = False):
text = code_re.sub(code_handler, text)
text = a_re.sub(inner_a_handler, text)
text = fix_url.sub(r'\1', text)
return MD_START + text + MD_END
return SC_OFF + '<div class="md">' + text + '</div>' + SC_ON
def keep_space(text):

View File

@@ -85,20 +85,21 @@ menu = MenuHandler(hot = _('hot'),
stats = _("stats"),
submit = _("submit"),
help = _("help"),
blog = _("blog"),
blog = _("the reddit blog"),
logout = _("logout"),
#reddit footer strings
feedback = _("feedback"),
bookmarklets = _("bookmarklets"),
socialite = _("socialite"),
socialite = _("socialite firefox extension"),
buttons = _("buttons"),
widget = _("widget"),
code = _("code"),
code = _("source code"),
mobile = _("mobile"),
store = _("store"),
ad_inq = _("advertise"),
ad_inq = _("advertise on reddit"),
toplinks = _("top links"),
#preferences
options = _('options'),
friends = _("friends"),
@@ -180,8 +181,9 @@ def menu_style(type):
lightdrop = ('dropdown', 'lightdrop'),
tabdrop = ('dropdown', 'tabdrop'),
srdrop = ('dropdown', 'srdrop'),
flatlist = ('flatlist', ''),
flatlist = ('flatlist', 'flat-list'),
tabmenu = ('tabmenu', ''),
flat_vert = ('flatlist', 'flat-vert'),
)
return d.get(type, default)
@@ -292,6 +294,10 @@ class NavButton(Styled):
when it is different from self.title)"""
return self.title
class OffsiteButton(NavButton):
def build(self, base_path = ''):
self.path = self.bare_path = self.dest
class SubredditButton(NavButton):
def __init__(self, sr):
self.sr = sr

View File

@@ -32,7 +32,7 @@ from r2.lib.traffic import load_traffic, load_summary
from r2.lib.captcha import get_iden
from r2.lib.filters import spaceCompress, _force_unicode, _force_utf8
from r2.lib.menus import NavButton, NamedButton, NavMenu, PageNameNav, JsButton
from r2.lib.menus import SubredditButton, SubredditMenu, menu
from r2.lib.menus import SubredditButton, SubredditMenu, OffsiteButton, menu
from r2.lib.strings import plurals, rand_strings, strings
from r2.lib.utils import title_to_url, query_string, UrlParser, to_js
from r2.lib.template_helpers import add_sr, get_domain
@@ -185,21 +185,69 @@ class Reddit(Wrapped):
def footer_nav(self):
"""navigation buttons in the footer."""
buttons = [NamedButton("help", False, nocname=True),
NamedButton("blog", False, nocname=True),
NamedButton("stats", False, nocname=True),
NamedButton("feedback", False),
NamedButton("bookmarklets", False),
NamedButton("socialite", False),
NamedButton("buttons", True),
NamedButton("widget", True),
NamedButton("code", False, nocname=True),
NamedButton("mobile", False, nocname=True),
NamedButton("store", False, nocname=True),
NamedButton("ad_inq", False, nocname=True),
]
return [NavMenu([NamedButton("toplinks", False),
NamedButton("mobile", False, nocname=True),
OffsiteButton("rss", dest = '/.rss'),
NamedButton("store", False, nocname=True),
NamedButton("stats", False, nocname=True),
NamedButton("feedback", False),],
title = 'site links', type = 'flat_vert',
separator = ''),
return NavMenu(buttons, base_path = "/", type = "flatlist")
NavMenu([NamedButton("help", False, nocname=True),
OffsiteButton("FAQ", dest = '/help/faq',
nocname=True),
OffsiteButton("reddiquette", nocname=True,
dest = '/help/reddiquette')],
title = 'help', type = 'flat_vert',
separator = ''),
NavMenu([NamedButton("bookmarklets", False),
NamedButton("buttons", True),
NamedButton("code", False, nocname=True),
NamedButton("socialite", False),
NamedButton("widget", True)],
title = 'reddit tools', type = 'flat_vert',
separator = ''),
NavMenu([NamedButton("blog", False, nocname=True),
OffsiteButton("our pet fish",
dest="http://justin.tv/reddit"),
NamedButton("ad_inq", False, nocname=True),
OffsiteButton('reddit.tv', "http://www.reddit.tv"),
OffsiteButton('redditall', "http://www.redditall.com"),],
title = 'about us', type = 'flat_vert',
separator = ''),
NavMenu([OffsiteButton('BaconBuzz',
"http://www.baconbuzz.com"),
OffsiteButton('Destructoid reddit',
"http://reddit.destructoid.com"),
OffsiteButton('TheCuteList',
"http://www.thecutelist.com"),
OffsiteButton('The Independent reddit',
"http://reddit.independent.co.uk"),
OffsiteButton('redditGadgetGuide',
"http://www.redditgadgetguide.com"),
OffsiteButton('WeHeartGossip',
"http://www.weheartgossip.com")],
title = 'brothers', type = 'flat_vert',
separator = ''),
NavMenu([OffsiteButton('Wired.com',
"http://www.wired.com"),
OffsiteButton('Ars Technica',
"http://www.arstechnica.com"),
OffsiteButton('Style.com',
"http://www.style.com"),
OffsiteButton('Portfolio.com',
"http://www.portfolio.com",
css_class="line-through"),
OffsiteButton('Epicurious.com',
"http://www.epicurious.com"),
OffsiteButton('Concierge.com',
"http://www.concierge.com")],
title = 'sisters', type = 'flat_vert',
separator = '')
]
def build_toolbars(self):
"""Sets the layout of the navigation topbar on a Reddit. The result
@@ -359,6 +407,9 @@ class BoringPage(Reddit):
def build_toolbars(self):
return [PageNameNav('nomenu', title = self.pagename)]
class HelpPage(BoringPage):
def build_toolbars(self):
return [PageNameNav('help', title = self.pagename)]
class FormPage(BoringPage):
"""intended for rendering forms with no rightbox needed or wanted"""

View File

@@ -61,6 +61,7 @@ class Account(Thing):
has_subscribed = False,
pref_media = 'subreddit',
share = {},
wiki_override = None,
)
def karma(self, kind, sr = None):
@@ -105,6 +106,13 @@ class Account(Thing):
karma = self.link_karma
return max(karma, 1) if karma > -1000 else karma
def can_wiki(self):
if self.wiki_override is not None:
return self.wiki_override
else:
return (self.link_karma >= g.WIKI_KARMA and
self.comment_karma >= g.WIKI_KARMA)
def all_karmas(self):
"""returns a list of tuples in the form (name, link_karma,
comment_karma)"""

View File

@@ -19,7 +19,7 @@ body {
z-index: 1;
}
html,body { height: 100%; }
/*html,body { height: 100%; }*/
/* IE dumbness patch. hidden input in a hidden block that is
* subsequently shown leads to the input to "show" and generate undesired
@@ -45,15 +45,10 @@ a:focus { -moz-outline-style: none; }
*/
.rounded {
-moz-border-radius-topleft: 7px;
-moz-border-radius-topright: 7px;
-moz-border-radius-bottomleft: 7px;
-moz-border-radius-bottomright: 7px;
-webkit-border-top-left-radius: 7px;
-webkit-border-top-right-radius: 7px;
-webkit-border-bottom-left-radius: 7px;
-webkit-border-bottom-right-radius: 7px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
}
.rounded .morelink {
-webkit-border-top-right-radius: 6px;
-moz-border-radius-topright: 6px;
@@ -98,6 +93,17 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; }
.flat-list form {display: inline; }
.flat-list .selected a { color: orangered; }
ul.flat-vert {text-align: left;}
.flat-vert .separator { margin: 0 }
.flat-vert.title {
font-family:helvetica,arial,verdana,sans-serif;
color: #777;
font-size: 18px;
font-weight: normal;
margin-bottom: 5px;
}
.separator { color: gray; margin: 0px .7ex 0px .7ex}
.pref-lang { font-weight: bold; }
@@ -562,6 +568,9 @@ before enabling */
.help p, .help form { margin: 5px; }
.help form { display: inline; }
.wikipage {
margin: 15px;
}
/* organic listing */
.organic-listing {
@@ -640,7 +649,7 @@ before enabling */
.infobar {
background-color: #f6e69f;
padding: 5px 10px;
margin: 5px 310px 5px 0px;
margin: 5px 305px 5px 0px;
border: 1px solid orange;
font-size: small;
}
@@ -754,7 +763,7 @@ a.star { text-decoration: none; color: #ff8b60 }
}
/* compressed links */
.linkcompressed { margin: 4px 0; overflow: hidden; }
.linkcompressed { margin: 4px 0; overflow: hidden; margin-top: 5px; }
.linkcompressed .title {margin-bottom: 1px; font-size:medium; font-weight: normal;}
.linkcompressed .child h3 {
margin: 15px;
@@ -765,7 +774,7 @@ a.star { text-decoration: none; color: #ff8b60 }
.linkcompressed .score.likes { color: #FF8B60; }
.linkcompressed .score.dislikes { color: #9494FF; }
.linkcompressed .rank {
margin-top: 4px;
margin-top: 5px;
float:left;
color: #c6c6c6;
font-family: arial;
@@ -780,7 +789,7 @@ a.star { text-decoration: none; color: #ff8b60 }
.linkcompressed .entry .buttons li.first {padding-left: .5em;}
.linkcompressed .entry .buttons li a {
padding: 0 2px;
background-color: #f3f3f3;
background-color: #f4f4f4;
font-weight: bold
}
@@ -967,23 +976,29 @@ textarea.gray { color: gray; }
/* footer */
.footer {
width: 100%;
text-align: center;
clear: both;
padding-top: 1em;
color: gray;
font-size: larger;
.footer-parent {
text-align: center;
}
.footer p { margin: 10px }
.footer {
clear: both;
color: gray;
font-size: larger;
padding: 5px;
margin: 15px;
border:1px solid #F0F0F0;
display: inline-block;
}
.wired a {text-decoration: underline;
color: #369;
font-size: smaller;
padding-left: 5px;
padding-right: 5px; }
.wired img {vertical-align: middle;}
.footer .col {
float: left;
margin: 10px;
padding-left: 10px;
border-left: 1px solid #E0E0E0;
height: 150px;
}
.footer .col:first-child {border: none;}
.server-status { width: 300px; }
.server-status table {
@@ -1095,6 +1110,7 @@ textarea.gray { color: gray; }
.status { color: red; }
.error { color: red; font-size: small; margin: 5px; }
.line-through { text-decoration: line-through }
#noresults { margin-right: 310px; }
@@ -1274,7 +1290,7 @@ textarea.gray { color: gray; }
font-weight: bold;
}
.bottommenu { color: gray; font-size: smaller; }
.bottommenu { color: gray; font-size: smaller; clear: both}
.bottommenu a { color: gray; text-decoration: underline; }

View File

@@ -0,0 +1,30 @@
## The contents of this file are subject to the Common Public Attribution
## License Version 1.0. (the "License"); you may not use this file except in
## compliance with the License. You may obtain a copy of the License at
## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
## License Version 1.1, but Sections 14 and 15 have been added to cover use of
## software over a computer network and provide for limited attribution for the
## Original Developer. In addition, Exhibit A has been modified to be consistent
## with Exhibit B.
##
## Software distributed under the License is distributed on an "AS IS" basis,
## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
## the specific language governing rights and limitations under the License.
##
## The Original Code is Reddit.
##
## The Original Developer is the Initial Developer. The Initial Developer of
## the Original Code is CondeNet, Inc.
##
## All portions of the code written by CondeNet are Copyright (c) 2006-2009
## CondeNet, Inc. All Rights Reserved.
################################################################################
<%inherit file="reddit.html"/>
<%def name="stylesheet()">
${parent.stylesheet()}
<link rel="stylesheet"
type="text/css"
href="http://code.reddit.com/chrome/reddit/style.css" />
</%def>

View File

@@ -57,12 +57,13 @@
<%def name="flatlist()">
<% css_class = str(thing.css_class) if thing.css_class else "" %>
%if thing:
%if thing.title:
<span class="flat-list title">${thing.title}:&#32;</span>
%endif
<ul class="flat-list hover"
<ul class="${css_class} hover"
${"id='%s'" % thing._id if thing._id else ""}>
%if thing.title:
<li class="${css_class} title">${thing.title}</li>
%endif
%for i, option in enumerate(thing):
<%
##option.title isn't the title, option.render() is the entire link

View File

@@ -38,6 +38,12 @@
<span class="pagename selected">${thing.title}</span>
</%def>
<%def name="help()">
<span class="hover pagename redditname">
${plain_link(thing.title, "/help", _sr_path=False)}
</span>
</%def>
<%def name="newpagelink()">
<span class="newpagelink">reddit all?&#32;${plain_link("click here to find new links.", "/new/", _sr_path=False)}</span>
</%def>

View File

@@ -29,25 +29,24 @@
<%namespace file="login.html" import="login_panel, login_form"/>
<%namespace file="utils.html" import="text_with_links, plain_link"/>
<div class="footer">
${thing.footer_nav().render()}
<div class="footer-parent">
<div class="footer rounded">
%for toolbar in thing.footer_nav():
<div class="col">
${toolbar.render()}
</div>
%endfor
<p class="wired">
<a rel="nofollow" target="_top" href="http://wired.com">
<img src="${static('wired_w.png')}" alt="wired" /></a>
<a rel="nofollow" target="_top" href="http://wired.com">WIRED.com</a>-
<a rel="nofollow" target="_top" href="http://howto.wired.com">WIRED How-To</a>
</p>
<p class="bottommenu">
${text_with_links(_("Use of this site constitutes acceptance of our %(user_agreement)s and %(privacy_policy)s"), nocname=True, user_agreement= (_("User Agreement {Genitive}"), "http://reddit.com/help/useragreement"), privacy_policy = (_("Privacy Policy {Genitive}"), "http://reddit.com/help/privacypolicy"))}.
${_("(c) %(year)d CondeNet, Inc. All rights reserved.") % \
dict(year=datetime.datetime.now().timetuple()[0])}
</p>
%if g.tracker_url and thing.site_tracking:
<img alt="" src="${tracking.UserInfo.gen_url()}"/>
%endif
<p class="bottommenu">
${text_with_links(_("Use of this site constitutes acceptance of our %(user_agreement)s and %(privacy_policy)s"), nocname=True, user_agreement= (_("User Agreement {Genitive}"), "http://reddit.com/help/useragreement"), privacy_policy = (_("Privacy Policy {Genitive}"), "http://reddit.com/help/privacypolicy"))}.
${_("(c) %(year)d CondeNet, Inc. All rights reserved.") % \
dict(year=datetime.datetime.now().timetuple()[0])}
</p>
%if g.tracker_url and thing.site_tracking:
<img alt="" src="${tracking.UserInfo.gen_url()}"/>
%endif
</div>
</div>
%if not c.user_is_loggedin:
%if thing.enable_login_cover:
${self.loginpopup(login_panel, login_form)}