Ticket #7249: trac_7249_jinja2_v4.patch

File trac_7249_jinja2_v4.patch, 50.9 KB (added by timdumol, 10 years ago)

Fixes the styling of the worksheet listing page.

  • sagenb/data/sage/css/main.css

    # HG changeset patch
    # User Mitesh Patel <qed777@gmail.com>
    # Date 1262813598 28800
    # Node ID c6ea40a1660c8effb509bcaeea18827d30ac3baf
    # Parent  f20b011f30dc307d9f79627a78f01150005db3d3
    #7249 Switch the notebook's templating system to Jinja2
    
    diff --git a/sagenb/data/sage/css/main.css b/sagenb/data/sage/css/main.css
    a b  
    3737
    3838hr.usercontrol { clear: both; float: left; }
    3939
    40 div#user-controls { overflow: hidden; display: inline-block; clear: both; border-bottom: 1px solid #c9d7f1; padding: 10px; }
    41 div#user-controls { display: block; }
     40div#user-main-controls { overflow: hidden; display: inline-block; clear: both; border-bottom: 1px solid #c9d7f1; padding: 10px; }
     41div#user-main-controls { display: block; }
    4242div#worksheet-list-controls { padding: 10px; clear: both; overflow: hidden; display: inline-block; }
    4343div#worksheet-list-controls { display: block; }
    4444div#worksheet-list-controls div.action-buttons { float: left; }
     
    305305
    306306span.worksheet_buttons { position: relative; top: -20ex; right: 0ex; }
    307307
     308
    308309.thin-right { position: absolute; top: auto; right: 0; width: 70%; }
    309310
    310311/* *********** User Home (Worksheet listing) ************************* */
     312#worksheet-listing-page #welcome-message { text-align: center; padding: 1em; }
     313
    311314.ratingmsg { color: #112abb; padding: 0.3em; font-size: 14px; }
    312315
    313316.pubmsg { font-family: sans-serif; color: #112abb; padding: 0.3em; font-size: 12px; }
  • sagenb/data/sage/html/base.html

    diff --git a/sagenb/data/sage/html/base.html b/sagenb/data/sage/html/base.html
    a b  
    1 {%- macro render_title -%}{% block title %}{% endblock %}{%- endmacro -%}
     1{%- macro render_title() -%}{% block title %}{% endblock %}{%- endmacro -%}
    22<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
    33<html lang="en">
    44    <head>
  • sagenb/data/sage/html/notebook/cell.html

    diff --git a/sagenb/data/sage/html/notebook/cell.html b/sagenb/data/sage/html/notebook/cell.html
    a b  
    1212        print or not.
    1313#}
    1414{% if do_print %}
    15     {% set wrap = 68 %}
    16     {% set div_wrap = true %}
     15    {% set wrap_ = 68 %}
     16    {% set div_wrap_ = true %}
     17{% else %}
     18    {% set wrap_ = wrap %}
     19    {% set div_wrap_ = div_wrap %}
    1720{% endif %}
    1821{% set cell_cls = "cell_evaluated" if cell.evaluated() or do_print else "cell_not_evaluated" %}
    1922
    20 {% if div_wrap %}
     23{% if div_wrap_ %}
    2124<div id="cell_outer_{{ cell.id() }}" class="cell_visible">
    2225    <div id="cell_{{ cell.id() }}" class="{{ cell_cls }}">
    2326{% endif %}
     
    5659                          onFocus="cell_focused(this, {{ cell.id() }}); return true;">{{ cell.input_text().rstrip() }}</textarea>
    5760                <a href="javascript:evaluate_cell({{ cell.id() }},0)"
    5861                   class="eval_button"
    59                    id="eval_button{{ cell.id() }}"
     62                   id="eval_button{{ cell.id() }}" 
    6063                   alt="Click here or press shift-return to evaluate">
    6164                    evaluate
    6265                </a>
     
    8588                                {% if cell.introspect() %}
    8689                                    {{ cell.output_text(0, html=true) }}
    8790                                {% else %}
    88                                     {{ cell.output_text(wrap, html=true) }}
     91                                    {{ cell.output_text(wrap_, html=true) }}
    8992                                {% endif %}
    9093                            </div>
    9194                            {% if not do_print %}
     
    105108        </div>
    106109        {% endif %}
    107110       
    108 {% if div_wrap %}
     111{% if div_wrap_ %}
    109112    </div>
    110113</div>
    111114{% endif %}
  • sagenb/data/sage/html/worksheet_listing.html

    diff --git a/sagenb/data/sage/html/worksheet_listing.html b/sagenb/data/sage/html/worksheet_listing.html
    a b  
    130130        </tr>
    131131        {% elif typ == 'active' %}
    132132        <tr>
    133             <td colspan="5">
     133            <td colspan="5" id="welcome-message">
    134134                Welcome to Sage! You can <a href="/new_worksheet">create a new worksheet</a>,
    135135                view <a href="/pub/">published worksheets</a>, or read the
    136136                <a href="/help" target="_new">documentation</a>.
  • sagenb/interfaces/expect.py

    diff --git a/sagenb/interfaces/expect.py b/sagenb/interfaces/expect.py
    a b  
    241241        # The magic comment at the very start of the file allows utf8 characters.
    242242        open(self._filename,'w').write(
    243243            '# -*- coding: utf_8 -*-\nimport sys;sys.ps1="%s";print "START%s"\n'%(
    244             self._prompt, self._number) + displayhook_hack(string))
     244            self._prompt, self._number) + displayhook_hack(string).encode('utf-8', 'ignore'))
    245245        try:
    246246            self._expect.sendline('\nimport os;os.chdir("%s");\nexecfile("%s")'%(
    247247                              remote, sage_input))
    248         except OSError, msg:
     248        except OSError as msg:
    249249            self._is_computing = False
    250250            self._so_far = str(msg)
    251251
  • sagenb/misc/misc.py

    diff --git a/sagenb/misc/misc.py b/sagenb/misc/misc.py
    a b  
     1# -*- coding: utf-8 -*-
    12"""
    23Miscellaneous Notebook Functions
    34"""
     
    384385        # TODO
    385386        raise NotImplementedError, "Curently %cython mode requires Sage."
    386387
    387 
    388388#############################################################
    389389# File permissions
    390390# May need some changes on Windows.
     
    402402             stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | \
    403403             stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP)
    404404
     405def encoded_str(obj, encoding='utf-8'):
     406    """
     407    Takes an object and returns an encoded str human-readable representation.
     408
     409    EXAMPLES::
     410
     411        sage: from sagenb.misc.misc import encoded_str
     412        sage: encoded_str(u'ĀƂḉПΣ')
     413        '\xc3\x84\xc2\x80\xc3\x86\xc2\x82\xc3\xa1\xc2\xb8\xc2\x89\xc3\x90\xc2\x9f\xc3\x8e\xc2\xa3'
     414        sage: encoded_str(u'abc')
     415        'abc'
     416        sage: encoded_str(123)
     417        '123'
     418    """
     419    if isinstance(obj, unicode):
     420        return obj.encode(encoding, 'ignore')
     421    return str(obj)
     422
     423def unicode_str(obj, encoding='utf-8'):
     424    """
     425    Takes an object and returns a unicode human-readable representation.
     426
     427    EXAMPLES::
     428
     429        sage: from sagenb.misc.misc import unicode_str
     430        sage: unicode_str('\xc3\x84\xc2\x80\xc3\x86\xc2\x82\xc3\xa1\xc2\xb8\xc2\x89\xc3\x90\xc2\x9f\xc3\x8e\xc2\xa3')
     431        u'\xc4\x80\xc6\x82\xe1\xb8\x89\xd0\x9f\xce\xa3'
     432        sage: unicode_str('\xc3\x84\xc2\x80\xc3\x86\xc2\x82\xc3\xa1\xc2\xb8\xc2\x89\xc3\x90\xc2\x9f\xc3\x8e\xc2\xa3') == u'ĀƂḉПΣ'
     433        True
     434        sage: unicode_str('abc')
     435        u'abc'
     436        sage: unicode_str(123)
     437        u'123'
     438    """
     439    if isinstance(obj, str):
     440        return obj.decode(encoding, 'ignore')
     441    return unicode(str(obj), encoding)
     442       
     443
    405444
    406445def ignore_nonexistent_files(curdir, dirlist):
    407446    """
  • sagenb/misc/sageinspect.py

    diff --git a/sagenb/misc/sageinspect.py b/sagenb/misc/sageinspect.py
    a b  
    483483
    484484    if r is None:
    485485        return ''
    486 
    487     s = format(str(r), embedded=EMBEDDED_MODE)
     486    if isinstance(r, unicode):
     487        r = r.encode('utf-8', 'ignore')
     488    else:
     489        r = str(r)
     490    s = format(r, embedded=EMBEDDED_MODE)
    488491
    489492    # If there is a Cython embedded position, it needs to be stripped
    490493    pos = _extract_embedded_position(s)
  • sagenb/misc/support.py

    diff --git a/sagenb/misc/support.py b/sagenb/misc/support.py
    a b  
    331331        filename = sageinspect.sage_getfile(obj)
    332332        try:
    333333            lines, lineno = sageinspect.sage_getsourcelines(obj, is_binary=False)
    334         except IOError, msg:
     334        except IOError as msg:
    335335            return html_markup(str(msg))
    336336        src = indent.join(lines)
    337337        src = indent + format_src(src)
     
    467467    if dir:
    468468        if hasattr(system.__class__, 'chdir'):
    469469            system.chdir(dir)
     470    if isinstance(cmd, unicode):
     471        cmd = cmd.encode('utf-8', 'ignore')
    470472    return system.eval(cmd, sage_globals, locals = sage_globals)
    471473
    472474######################################################################
  • sagenb/notebook/cell.py

    diff --git a/sagenb/notebook/cell.py b/sagenb/notebook/cell.py
    a b  
    1818
    1919from   sagenb.misc.misc import (word_wrap, SAGE_DOC,
    2020                                strip_string_literals,
    21                                 set_restrictive_permissions)
     21                                set_restrictive_permissions,
     22                                unicode_str)
    2223
    2324from   jsmath import math_parse
    2425
     
    9192            sage: C == loads(dumps(C))
    9293            True
    9394        """
     95        text = unicode_str(text)
    9496        self.__id = int(id)
    9597        self.__text = text
    9698        self.__worksheet = worksheet
     
    103105
    104106            sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None)
    105107            sage: C.__repr__()
    106             'TextCell 0: 2+3'
     108            u'TextCell 0: 2+3'
    107109        """
    108110        return "TextCell %s: %s"%(self.__id, self.__text)
    109111
     
    136138            sage: C
    137139            TextCell 0: 3+2
    138140        """
     141        input_text = unicode_str(input_text)
    139142        self.__text = input_text
    140143
    141144    def set_worksheet(self, worksheet, id=None):
     
    179182        - ``wrap`` -- number of columns to wrap at (not used)
    180183
    181184        - ``div_wrap`` -- whether to wrap in a div (not used)
    182        
     185
    183186        - ``do_math_parse`` - bool (default: True)
    184187          If True, call math_parse (defined in cell.py)
    185188          on the html.
     
    192195
    193196        EXAMPLES::
    194197
    195             sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None)
     198            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb')
     199            sage: nb.add_user('sage','sage','sage@sagemath.org',force=True)
     200            sage: W = nb.create_new_worksheet('Test', 'sage')
     201            sage: C = sagenb.notebook.cell.TextCell(0, '2+3', W)
    196202            sage: C.html()
    197203            u'...text_cell...2+3...'
    198204            sage: C.set_input_text("$2+3$")
     
    214220
    215221            sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None)
    216222            sage: C.plain_text()
    217             '2+3'
     223            u'2+3'
    218224        """
    219225        return self.__text
    220226
     
    226232
    227233            sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None)
    228234            sage: C.edit_text()
    229             '2+3'
     235            u'2+3'
    230236        """
    231237        return self.__text
    232238
     
    297303            sage: C == loads(dumps(C))
    298304            True
    299305        """
     306        out = unicode_str(out)
     307        input = unicode_str(input)
     308
    300309        self.__id    = int(id)
    301         self.__out   = str(out).replace('\r','')
     310        self.__out   = out.replace('\r','')
    302311        self.__worksheet = worksheet
    303312        self.__interrupted = False
    304313        self.__completions = False
     
    355364            sage: C
    356365            Cell 0; in=2+3, out=
    357366        """
    358         self.__out = ''
    359         self.__out_html = ''
     367        self.__out = u''
     368        self.__out_html = u''
    360369        self.__evaluated = False
    361370
    362371    def evaluated(self):
     
    555564            sage: nb.delete()
    556565        """
    557566        if self.is_interactive_cell():
    558             self.__out_html = ""
     567            self.__out_html = u""
    559568        else:
    560569            self.__out_html = self.files_html(output)
    561570
     
    735744        """
    736745        if ncols == 0:
    737746            ncols = self.word_wrap_cols()
    738         s = ''
     747        s = u''
     748
     749        self.__in = unicode_str(self.__in)
    739750
    740751        input_lines = self.__in
     752
    741753        pr = 'sage: '
    742754
    743755        if prompts:
     
    810822
    811823            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None)
    812824            sage: C.edit_text()
    813             '{{{id=0|\n2+3\n///\n5\n}}}'
     825            u'{{{id=0|\n2+3\n///\n5\n}}}'
    814826        """
    815827        s = self.plain_text(ncols, prompts, max_out)
    816         return '{{{id=%s|\n%s\n}}}'%(self.id(), s)
     828        return u'{{{id=%s|\n%s\n}}}'%(self.id(), s)
    817829
    818830    def is_last(self):
    819831        """
     
    9881000            0
    9891001            sage: C.set_input_text('3+3')
    9901002            sage: C.input_text()
    991             '3+3'
     1003            u'3+3'
    9921004            sage: C.evaluated()
    9931005            False
    9941006            sage: C.version()
     
    9971009            sage: nb.delete()
    9981010        """
    9991011        # Stuff to deal with interact
     1012        input = unicode_str(input)
     1013
    10001014        if input.startswith('%__sage_interact__'):
    10011015            self.interact = input[len('%__sage_interact__')+1:]
    10021016            self.__version = self.version() + 1
     
    10281042
    10291043            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None)
    10301044            sage: C.input_text()
    1031             '2+3'
     1045            u'2+3'
    10321046        """
    10331047        return self.__in
    10341048
     
    10421056
    10431057            sage: C = sagenb.notebook.cell.Cell(0, '%hide\n%maxima\n2+3', '5', None)
    10441058            sage: C.cleaned_input_text()
    1045             '2+3'
     1059            u'2+3'
    10461060        """
    10471061        if self.is_interacting():
    10481062            return self.interact
     
    10601074
    10611075            sage: C = sagenb.notebook.cell.Cell(0, '%hide\n%maxima\n2+3', '5', None)
    10621076            sage: C.parse_percent_directives()
    1063             '2+3'
     1077            u'2+3'
    10641078            sage: C.percent_directives()
    1065             ['hide', 'maxima']
     1079            [u'hide', u'maxima']
    10661080        """
    10671081        self._system = None
    10681082        text = self.input_text().splitlines()
     
    10971111
    10981112            sage: C = sagenb.notebook.cell.Cell(0, '%hide\n%maxima\n2+3', '5', None)
    10991113            sage: C.percent_directives()
    1100             ['hide', 'maxima']
     1114            [u'hide', u'maxima']
    11011115        """
    11021116        return self._percent_directives
    11031117
     
    11151129
    11161130            sage: C = sagenb.notebook.cell.Cell(0, '%maxima\n2+3', '5', None)
    11171131            sage: C.system()
    1118             'maxima'
     1132            u'maxima'
    11191133            sage: prefixes = ['%hide', '%time', '']
    11201134            sage: cells = [sagenb.notebook.cell.Cell(0, '%s\n2+3'%prefix, '5', None) for prefix in prefixes]
    11211135            sage: [(C, C.system()) for C in cells if C.system() is not None]
     
    11551169            ''
    11561170            sage: C.set_changed_input_text('3+3')
    11571171            sage: C.input_text()
    1158             '3+3'
     1172            u'3+3'
    11591173            sage: C.changed_input_text()
    1160             '3+3'
     1174            u'3+3'
    11611175            sage: C.changed_input_text()
    11621176            ''
    11631177            sage: C.version()
     
    11801194            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None)
    11811195            sage: C.set_changed_input_text('3+3')
    11821196            sage: C.input_text()
    1183             '3+3'
     1197            u'3+3'
    11841198            sage: C.changed_input_text()
    1185             '3+3'
     1199            u'3+3'
    11861200        """
     1201        new_text = unicode_str(new_text)
     1202
    11871203        self.__changed_input = new_text
    11881204        self.__in = new_text
    11891205
     
    12001216            sage: len(C.plain_text())
    12011217            12
    12021218        """
     1219        output = unicode_str(output)
     1220        html = unicode_str(html)
    12031221        if output.count('<?__SAGE__TEXT>') > 1:
    1204             html = '<h3><font color="red">WARNING: multiple @interacts in one cell disabled (not yet implemented).</font></h3>'
    1205             output = ''
     1222            html = u'<h3><font color="red">WARNING: multiple @interacts in one cell disabled (not yet implemented).</font></h3>'
     1223            output = u''
    12061224
    12071225        # In interacting mode, we just save the computed output
    12081226        # (do not overwrite).
     
    12221240            url = ""
    12231241            if not self.computing():
    12241242                file = os.path.join(self.directory(), "full_output.txt")
    1225                 open(file,"w").write(output)
     1243                open(file,"w").write(output.encode('utf-8', 'ignore'))
    12261244                url = "<a target='_new' href='%s/full_output.txt' class='file_link'>full_output.txt</a>"%(
    12271245                    self.url_to_self())
    12281246                html+="<br>" + url
     
    12651283            ''
    12661284            sage: C.set_output_text('5', '<strong>5</strong>')
    12671285            sage: C.output_html()
    1268             '<strong>5</strong>'
     1286            u'<strong>5</strong>'
    12691287        """
    12701288        try:
    12711289            return self.__out_html
     
    13201338            sage: W = nb.create_new_worksheet('Test', 'sage')
    13211339            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', W)
    13221340            sage: C.output_text()
    1323             '<pre class="shrunk">5</pre>'
     1341            u'<pre class="shrunk">5</pre>'
    13241342            sage: C.output_text(html=False)
    1325             '<pre class="shrunk">5</pre>'
     1343            u'<pre class="shrunk">5</pre>'
    13261344            sage: C.output_text(raw=True)
    1327             '5'
     1345            u'5'
    13281346        """
    13291347        if allow_interact and hasattr(self, '_interact_output'):
    13301348            # Get the input template
     
    13481366                # during interact.
    13491367                return ''
    13501368
     1369        self.__out = unicode_str(self.__out)
     1370
    13511371        is_interact = self.is_interactive_cell()
    13521372        if is_interact and ncols == 0:
    13531373            if 'Traceback (most recent call last)' in self.__out:
    13541374                s = self.__out.replace('cell-interact','')
    13551375                is_interact=False
    13561376            else:
    1357                 return '<h2>Click to the left again to hide and once more to show the dynamic interactive window</h2>'
     1377                return u'<h2>Click to the left again to hide and once more to show the dynamic interactive window</h2>'
    13581378        else:
    13591379            s = self.__out
    13601380
     
    14481468
    14491469            sage: C = sagenb.notebook.cell.Cell(0, "%html\nTest HTML", None, None)
    14501470            sage: C.system()
    1451             'html'
     1471            u'html'
    14521472            sage: C.is_html()
    14531473            True
    14541474            sage: C = sagenb.notebook.cell.Cell(0, "Test HTML", None, None)
     
    14951515            ('d', Cell 0; in=sage?, out=)
    14961516            sage: C.set_introspect_html('foobar')
    14971517            sage: C.introspect_html()
    1498             'foobar'
     1518            u'foobar'
    14991519            sage: C.set_introspect_html('`foobar`')
    15001520            sage: C.introspect_html()
    1501             '`foobar`'
     1521            u'`foobar`'
    15021522            sage: W.quit()
    15031523            sage: nb.delete()
    15041524        """
     1525        html = unicode_str(html)
     1526
    15051527        self.__introspect_html = html
    15061528        self.introspection_status = 'done'
    15071529
     
    15421564        try:
    15431565            return self.__introspect_html
    15441566        except AttributeError:
    1545             self.__introspect_html = ''
    1546             return ''
     1567            self.__introspect_html = u''
     1568            return u''
    15471569
    15481570    def introspect(self):
    15491571        """
     
    15611583            sage: W.check_comp(9999)     # random output -- depends on computer speed
    15621584            ('d', Cell 0; in=sage?, out=)
    15631585            sage: C.introspect()
    1564             ['sage?', '']
     1586            [u'sage?', '']
    15651587            sage: W.quit()
    15661588            sage: nb.delete()
    15671589        """
     
    15861608            sage: W.check_comp(9999)     # random output -- depends on computer speed
    15871609            ('d', Cell 0; in=sage?, out=)
    15881610            sage: C.introspect()
    1589             ['sage?', '']
     1611            [u'sage?', '']
    15901612            sage: C.unset_introspect()
    15911613            sage: C.introspect()
    15921614            False
     
    17351757
    17361758        if wrap is None:
    17371759            wrap = self.notebook().conf()['word_wrap_cols']
    1738            
     1760
    17391761        return template(os.path.join('html', 'notebook', 'cell.html'),
    17401762                        cell=self, wrap=wrap,
    17411763                        div_wrap=div_wrap, do_print=do_print)
     
    19081930            files  = ''
    19091931        else:
    19101932            files  = ('&nbsp'*3).join(files)
     1933
     1934        files = unicode_str(files)
     1935        images = unicode_str(images)
     1936
    19111937        return images + files
    19121938
    19131939########
  • new file sagenb/notebook/misc.py

    diff --git a/sagenb/notebook/misc.py b/sagenb/notebook/misc.py
    new file mode 100644
    - +  
     1"""
     2Miscellaneus functions used by the Sage Notebook
     3
     4
     5"""
     6
  • sagenb/notebook/notebook.py

    diff --git a/sagenb/notebook/notebook.py b/sagenb/notebook/notebook.py
    a b  
    3232
    3333# Sage libraries
    3434from sagenb.misc.misc import (pad_zeros, cputime, tmp_dir, load, save,
    35                               ignore_nonexistent_files)
     35                              ignore_nonexistent_files, encoded_str)
    3636
    3737# Sage Notebook
    3838import css          # style
     
    934934            return self._user_history[username]
    935935        history = []
    936936        for hunk in self.__storage.load_user_history(username):
    937             if isinstance(hunk, str):
    938                 hunk = unicode(hunk.decode('utf-8', 'ignore'))
     937            hunk = encoded_str(hunk)
    939938            history.append(hunk)
    940939        self._user_history[username] = history
    941940        return history
     
    10521051        W is our newly-created worksheet, with the 2+3 cell in it::
    10531052
    10541053            sage: W.name()
    1055             'foo'
     1054            u'foo'
    10561055            sage: W.cell_list()
    10571056            [TextCell 0: foo, Cell 1; in=2+3, out=]
    10581057        """
     
    12661265            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb')
    12671266            sage: W = nb.create_new_worksheet('Test', 'admin')
    12681267            sage: W.body()
    1269             '\n\n{{{id=1|\n\n///\n}}}'
     1268            u'\n\n{{{id=1|\n\n///\n}}}'
    12701269            sage: W.save_snapshot('admin')
    12711270            sage: nb.html_worksheet_revision_list('admin', W)
    12721271            u'...Revision...Last Edited...ago...'
     
    12751274
    12761275        return template(os.path.join("html", "notebook", "worksheet_revision_list.html"),
    12771276                        data = data, worksheet = worksheet,
    1278                         worksheet_filename = worksheet.filename(),
     1277                        notebook = self,
    12791278                        username = username)
    12801279
    12811280
     
    13471346
    13481347        return template(os.path.join("html", "notebook", "worksheet_share.html"),
    13491348                        worksheet = worksheet,
    1350                         worksheet_filename = worksheet.filename(),
     1349                        notebook = self,
    13511350                        username = username, other_users = other_users)
    13521351   
    13531352    def html_download_or_delete_datafile(self, ws, username, filename):
     
    13841383            text_file_content = open(os.path.join(ws.data_directory(), filename)).read()
    13851384
    13861385        return template(os.path.join("html", "notebook", "download_or_delete_datafile.html"),
    1387                         worksheet = ws, worksheet_filename = ws.filename(),
     1386                        worksheet = ws, notebook = self,
    13881387                        username = username,
    13891388                        filename_ = filename,
    13901389                        file_is_image = file_is_image,
     
    15041503
    15051504        return template(os.path.join("html", "notebook", "plain_text_window.html"),
    15061505                        worksheet = worksheet,
    1507                         worksheet_filename = worksheet.filename(),
     1506                        notebook = self,
    15081507                        username = username, plain_text = plain_text,
    15091508                        JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE)
    15101509
     
    15321531
    15331532        return template(os.path.join("html", "notebook", "edit_window.html"),
    15341533                        worksheet = worksheet,
    1535                         worksheet_filename = worksheet.filename(),
     1534                        notebook = self,
    15361535                        username = username)
    15371536
    15381537    def html_beforepublish_window(self, worksheet, username):
     
    15691568        """
    15701569        return template(os.path.join("html", "notebook", "beforepublish_window.html"),
    15711570                        worksheet = worksheet,
    1572                         worksheet_filename = worksheet.filename(),
    1573                         username = username,
    1574                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE)
     1571                        notebook = self,
     1572                        username = username)
    15751573
    15761574    def html_afterpublish_window(self, worksheet, username, url, dtime):
    15771575        r"""
     
    15981596
    15991597        return template(os.path.join("html", "notebook", "afterpublish_window.html"),
    16001598                        worksheet = worksheet,
    1601                         worksheet_filename = worksheet.filename(),
    1602                         username = username, url = url, time = time,
    1603                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE)
     1599                        notebook = self,
     1600                        username = username, url = url, time = time)
    16041601
    16051602    def html_upload_data_window(self, ws, username):
    16061603        r"""
  • sagenb/notebook/template.py

    diff --git a/sagenb/notebook/template.py b/sagenb/notebook/template.py
    a b  
    1515#                  http://www.gnu.org/licenses/
    1616#############################################################################
    1717
    18 import jinja
    19 
    20 from jinja.filters import stringfilter, simplefilter
     18import jinja2
    2119
    2220import os, re, sys
    2321
     
    2725
    2826
    2927TEMPLATE_PATH = os.path.join(DATA, 'sage')
    30 env = jinja.Environment(loader=jinja.FileSystemLoader(TEMPLATE_PATH))
     28env = jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATE_PATH))
    3129
    3230css_illegal_re = re.compile(r'[^-A-Za-z_0-9]')
    3331
    34 @stringfilter
    3532def css_escape(string):
    3633    r"""
    3734    Returns a string with all characters not legal in a css name
     
    4340
    4441    EXAMPLES::
    4542
    46         sage: from sagenb.notebook.template import env, css_escape
    47         sage: escaper = css_escape()
    48         sage: print(escaper(env, {}, '12abcd'))
    49         12abcd
    50         sage: print(escaper(env, {}, 'abcd'))
    51         abcd
    52         sage: print(escaper(env, {}, r'\'"abcd\'"'))
    53         ---abcd---
    54         sage: print(escaper(env, {}, 'my-invalid/identifier'))
    55         my-invalid-identifier
    56         sage: print(escaper(env, {}, r'quotes"mustbe!escaped'))
    57         quotes-mustbe-escaped
    58 
    59     The following doctests originally accompanied #7269's support for
    60     Jinja2.
    61 
    62         sage: from sagenb.notebook.template import css_escape # not tested
    63         sage: css_escape('abcd')                              # not tested
     43        sage: from sagenb.notebook.template import css_escape
     44        sage: css_escape('abcd')
    6445        'abcd'
    65         sage: css_escape('12abcd')                            # not tested
     46        sage: css_escape('12abcd')
    6647        '12abcd'
    67         sage: css_escape(r'\'"abcd\'"')                       # not tested
     48        sage: css_escape(r'\'"abcd\'"')
    6849        '---abcd---'
    69         sage: css_escape('my-invalid/identifier')             # not tested
     50        sage: css_escape('my-invalid/identifier')
    7051        'my-invalid-identifier'
    71         sage: css_escape(r'quotes"mustbe!escaped')            # not tested
     52        sage: css_escape(r'quotes"mustbe!escaped')
    7253        'quotes-mustbe-escaped'
    7354    """
    7455    return css_illegal_re.sub('-', string)
     
    119100    return ''.join([x if x.isalnum() else '_' for x in name])
    120101
    121102env.filters['css_escape'] = css_escape
    122 env.filters['number_of_rows'] = simplefilter(number_of_rows)
    123 env.filters['clean_name'] = stringfilter(clean_name)
    124 env.filters['prettify_time_ago'] = simplefilter(prettify_time_ago)
    125 env.filters['math_parse'] = stringfilter(math_parse)
    126 env.filters['max'] = simplefilter(max)
     103env.filters['number_of_rows'] = number_of_rows
     104env.filters['clean_name'] = clean_name
     105env.filters['prettify_time_ago'] = prettify_time_ago
     106env.filters['math_parse'] = math_parse
     107env.filters['max'] = max
    127108
    128109def template(filename, **user_context):
    129110    """
     
    139120      the file's template variables
    140121
    141122    OUTPUT:
    142    
     123
    143124    - a string - the rendered HTML, CSS, etc.
    144125
    145126    EXAMPLES::
     
    164145                       'conf': notebook.conf() if notebook else None}
    165146    try:
    166147        tmpl = env.get_template(filename)
    167     except jinja.exceptions.TemplateNotFound:
     148    except jinja2.exceptions.TemplateNotFound:
    168149        return "Notebook Bug -- missing template %s"%filename
    169150    context = dict(default_context)
    170151    context.update(user_context)
  • sagenb/notebook/twist.py

    diff --git a/sagenb/notebook/twist.py b/sagenb/notebook/twist.py
    a b  
    5252
    5353from sagenb.misc.misc import (SAGE_DOC, DATA, SAGE_VERSION, walltime,
    5454                              tmp_filename, tmp_dir, is_package_installed,
    55                               jsmath_macros)
     55                              jsmath_macros, encoded_str, unicode_str)
    5656
    5757css_path             = os.path.join(DATA, "sage", "css")
    5858image_path           = os.path.join(DATA, "sage", "images")
     
    8282SEP = '___S_A_G_E___'
    8383
    8484def encode_list(v):
    85     return SEP.join([str(x) for x in v])
     85    seq = []
     86    for x in v:
     87        x = encoded_str(x)
     88        seq.append(x)
     89    return SEP.join(seq)
    8690
    8791
    8892
     
    150154    """
    151155    def __init__(self, code=None, headers=None, stream=None):
    152156        if stream is not None:
    153             if isinstance(stream, unicode):
    154                 stream = stream.encode('utf-8', 'ignore')
     157            stream = encoded_str(stream)
    155158        super(Response, self).__init__(code, headers, stream)
    156159
    157160def HTMLResponse(*args, **kwds):
     
    10921095    def render(self, ctx):
    10931096        id = self.id(ctx)
    10941097        if not ctx.args.has_key('input'):
    1095             input = ''
     1098            input = u''
    10961099        else:
    10971100            input = ctx.args['input'][0]
     1101            input = unicode_str(input)
    10981102
    10991103        cell = self.worksheet.new_cell_before(id, input=input)
    11001104        self.worksheet.increase_state_number()
     
    11111115            input = ''
    11121116        else:
    11131117            input = ctx.args['input'][0]
     1118            input = unicode_str(input)
    11141119
    11151120        cell = self.worksheet.new_text_cell_before(id, input=input)
    11161121        s = encode_list([cell.id(), cell.html(editing=True), id])
     
    11271132            input = ''
    11281133        else:
    11291134            input = ctx.args['input'][0]
     1135            input = unicode_str(input)
     1136
    11301137        cell = self.worksheet.new_cell_after(id, input=input)
    11311138        s = encode_list([cell.id(), cell.html(div_wrap=False), id])
    11321139        return HTMLResponse(stream = s)
     
    11411148            input = ''
    11421149        else:
    11431150            input = ctx.args['input'][0]
     1151            input = unicode_str(input)
    11441152
    11451153        cell = self.worksheet.new_text_cell_after(id, input=input)
    11461154        s = encode_list([cell.id(), cell.html(editing=True), id])
     
    12021210        if status == 'd':
    12031211            new_input = cell.changed_input_text()
    12041212            out_html = cell.output_html()
    1205             try:
    1206                 H = "Worksheet '%s' (%s)\n"%(worksheet.name(), time.strftime("%Y-%m-%d at %H:%M",time.localtime(time.time())))
    1207                 H += cell.edit_text(ncols=HISTORY_NCOLS, prompts=False,
    1208                                     max_out=HISTORY_MAX_OUTPUT)
    1209                 notebook.add_to_user_history(H, self.username)
    1210             except UnicodeDecodeError:
    1211                 pass
     1213            H = "Worksheet '%s' (%s)\n"%(worksheet.name(), time.strftime("%Y-%m-%d at %H:%M",time.localtime(time.time())))
     1214            H += cell.edit_text(ncols=HISTORY_NCOLS, prompts=False,
     1215                                max_out=HISTORY_MAX_OUTPUT)
     1216            notebook.add_to_user_history(H, self.username)
    12121217        else:
    12131218            new_input = ''
    12141219            out_html = ''
     
    12541259    def render(self, ctx):
    12551260        id = self.id(ctx)
    12561261        if not ctx.args.has_key('input'):
    1257             input_text = ''
     1262            input_text = u''
    12581263        else:
    12591264            input_text = ctx.args['input'][0]
    12601265            input_text = input_text.replace('\r\n', '\n')   # DOS
     1266            input_text = unicode_str(input_text)
    12611267
    12621268        W = self.worksheet
    12631269        W.increase_state_number()
  • sagenb/notebook/worksheet.py

    diff --git a/sagenb/notebook/worksheet.py b/sagenb/notebook/worksheet.py
    a b  
    3131                              alarm, cancel_alarm, verbose, DOT_SAGENB,
    3232                              walltime, ignore_nonexistent_files,
    3333                              set_restrictive_permissions,
    34                               set_permissive_permissions)
     34                              set_permissive_permissions,
     35                              encoded_str, unicode_str)
    3536
    3637from sagenb.misc.remote_file import get_remote_file
    3738
     
    271272            sage: import sagenb.notebook.worksheet
    272273            sage: W = sagenb.notebook.worksheet.Worksheet('test', 0, tmp_dir(), owner='sage')
    273274            sage: sorted((W.basic().items()))
    274             [('auto_publish', False),
    275               ('collaborators', []),
    276               ('id_number', 0),
    277               ('last_change', ('sage', ...)),
    278               ('name', 'test'),
    279               ('owner', 'sage'),
    280               ('pretty_print', False),
    281               ('published_id_number', None),
    282               ('ratings', []),
    283               ('system', None),
    284               ('tags', {'sage': [1]}),
    285               ('viewers', []),
    286               ('worksheet_that_was_published', ('sage', 0))]
     275            [('auto_publish', False), ('collaborators', []), ('id_number', 0), ('last_change', ('sage', ...)), ('name', u'test'), ('owner', 'sage'), ('pretty_print', False), ('published_id_number', None), ('ratings', []), ('system', None), ('tags', {'sage': [1]}), ('viewers', []), ('worksheet_that_was_published', ('sage', 0))]
    287276        """
    288277        try:
    289278            published_id_number = int(os.path.split(self.__published_version)[1])
     
    690679            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb')
    691680            sage: W = nb.create_new_worksheet('A Test Worksheet', 'admin')
    692681            sage: W.name()
    693             'A Test Worksheet'
     682            u'A Test Worksheet'
    694683        """
    695684        try:
    696685            return self.__name
     
    712701            sage: W = nb.create_new_worksheet('A Test Worksheet', 'admin')
    713702            sage: W.set_name('A renamed worksheet')
    714703            sage: W.name()
    715             'A renamed worksheet'
     704            u'A renamed worksheet'
    716705        """
    717706        if len(name.strip()) == 0:
    718             name = 'Untitled'
     707            name = u'Untitled'
     708        name = unicode_str(name)
    719709        self.__name = name
    720710
    721711    def set_filename_without_owner(self, nm):
     
    19131903        if os.path.exists(worksheet_html) and open(worksheet_html).read() == E:
    19141904            # we already wrote it out...
    19151905            return
    1916         open(filename, 'w').write(bz2.compress(E))
    1917         open(worksheet_html, 'w').write(self.body())
     1906        open(filename, 'w').write(bz2.compress(E.encode('utf-8', 'ignore')))
     1907        open(worksheet_html, 'w').write(self.body().encode('utf-8', 'ignore'))
    19181908        self.limit_snapshots()
    19191909        try:
    19201910            X = self.__saved_by_info
     
    21412131            5, Cell 1; in=2+8, out=
    21422132            10]
    21432133            sage: W.name()
    2144             'Test Edit Save'
     2134            u'Test Edit Save'
    21452135        """
    21462136        # Clear any caching.
    21472137        try:
     
    34513441        """
    34523442        # The extra newline below is necessary, since otherwise source
    34533443        # code introspection doesn't include the last line.
    3454         return 'open("%s","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("%s"),globals())+"\\n"); execfile(os.path.abspath("%s"))'%(CODE_PY, base64.b64encode(s), CODE_PY)
     3444        return 'open("%s","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("%s"),globals())+"\\n"); execfile(os.path.abspath("%s"))'%(CODE_PY, base64.b64encode(s.encode('utf-8', 'ignore')), CODE_PY)
    34553445
    34563446    ##########################################################
    34573447    # Loading and attaching files
     
    36083598            sage: W.get_cell_system(c0)
    36093599            'sage'
    36103600            sage: W.get_cell_system(c1)
    3611             'gap'
     3601            u'gap'
    36123602            sage: W.edit_save('{{{\n%sage\n2+3\n}}}\n\n{{{\nSymmetricGroup(5)\n}}}')
    36133603            sage: W.set_system('gap')
    36143604            sage: c0, c1 = W.cell_list()
    36153605            sage: W.get_cell_system(c0)
    3616             'sage'
     3606            u'sage'
    36173607            sage: W.get_cell_system(c1)
    36183608            'gap'
    36193609        """
     
    36383628            os.makedirs(code)
    36393629        spyx = os.path.abspath(os.path.join(code, 'sage%s.spyx'%id))
    36403630        if not (os.path.exists(spyx) and open(spyx).read() == cmd):
    3641             open(spyx,'w').write(cmd)
     3631            open(spyx,'w').write(cmd.encode('utf-8', 'ignore'))
    36423632        return '_support_.cython_import_all("%s", globals())'%spyx
    36433633
    36443634    def check_for_system_switching(self, input, cell):
     
    36653655            sage: W.edit_save('{{{\n2+3\n}}}\n\n{{{\n%gap\nSymmetricGroup(5)\n}}}')
    36663656            sage: c0, c1 = W.cell_list()
    36673657            sage: W.check_for_system_switching(c0.cleaned_input_text(), c0)
    3668             (False, '2+3')
     3658            (False, u'2+3')
    36693659            sage: W.check_for_system_switching(c1.cleaned_input_text(), c1)
    3670             (True, "print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')")
     3660            (True, u"print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')")
    36713661
    36723662        ::
    36733663
     
    36893679            sage: W.set_system('gap')
    36903680            sage: c0, c1 = W.cell_list()
    36913681            sage: W.check_for_system_switching(c0.cleaned_input_text(), c0)
    3692             (False, '2+3')
     3682            (False, u'2+3')
    36933683            sage: W.check_for_system_switching(c1.cleaned_input_text(), c1)
    3694             (True,
    3695              "print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')")
     3684            (True, u"print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')")
    36963685            sage: c0.evaluate()
    36973686            sage: W.check_comp()  #random output -- depends on the computer's speed
    36983687            ('d', Cell 0; in=%sage
  • sagenb/storage/filesystem_storage.py

    diff --git a/sagenb/storage/filesystem_storage.py b/sagenb/storage/filesystem_storage.py
    a b  
    3939import os
    4040
    4141from abstract_storage import Datastore
    42 from sagenb.misc.misc import set_restrictive_permissions
     42from sagenb.misc.misc import set_restrictive_permissions, encoded_str
    4343
    4444def is_safe(a):
    4545    """
     
    291291            # only save if loaded
    292292            # todo -- add check if changed
    293293            filename = self._worksheet_html_filename(username, id_number)
    294             open(self._abspath(filename),'w').write(worksheet.body())
     294            open(self._abspath(filename),'w').write(worksheet.body().encode('utf-8', 'ignore'))
    295295
    296296    def load_worksheet(self, username, id_number):
    297297        """
     
    339339        if title:
    340340            # change the title
    341341            basic['name'] = title
    342 
     342        basic['name'] = encoded_str(basic['name'])
    343343        # Remove metainformation that perhaps shouldn't be distributed
    344344        for k in ['owner', 'ratings', 'worksheet_that_was_published', 'viewers', 'tags', 'published_id_number',
    345345                  'collaborators', 'auto_publish']:
     
    397397
    398398        worksheet_txt = members[0].name
    399399        W = self.load_worksheet(username, id_number)
    400         W.edit_save_old_format(T.extractfile(worksheet_txt).read())
     400        W.edit_save_old_format(T.extractfile(worksheet_txt).read().decode('utf-8', 'ignore'))
    401401        # '/' is right, since old worksheets always unix
    402402        dir = worksheet_txt.split('/')[0]
    403403           
  • sagenb/todo.txt

    diff --git a/sagenb/todo.txt b/sagenb/todo.txt
    a b  
    77    sage: notebook()  # then let the notebook start up, then hit ctrl-c
    88    sage: pwd -->  '/Users/palmieri/.sage' 
    99
    10 [ ] rate a worksheet -- note that the top of the browser (title) says
    11 error, though in fact there is no error.
    12 
    1310[ ] admin should *NOT* see all users worksheets.  This is not good, e.g.,
    1411when there are 50,000 worksheets!
    1512
     
    7067[ ] "untitled renaming".  Make it an option in the user confs, which
    7168is on by default, by you can turn it off.
    7269
    73 [ ] add message to the top of each *old* sage notebook .py file
    74  stating that one should work on sagenb instead.  This is a patch to
    75  the core Sage library.
    76 
    77 [ ] fix all doctests in sagenb code and make a patch against core
    78 sage library that imports enough of sagenb by default so I can
    79 run all these doctests. 
    8070
    8171[ ] get coverage to 100%.
    8272
    83 [ ] change to 100% html format for worksheets.
    8473
    8574[ ] we can make it so that if worksheet.html file changes on disk but
    8675not currently open, then when reopen it uses the new version from
     
    10998
    11099[ ] Jonathan Gutow -- redo how jmol works
    111100
    112 [ ] notebook docs -- something in "doc/en/sagenb"
     101
    113102
    114103[ ] maybe get rid of list of 'Sage Users' when publishing worksheets --
    115104that's not appropriate given how sage has grown.
     
    139128[ ] ldap support (see, eg., http://math.univ-lyon1.fr/~tdumont/sage)  but make sure to first
    140129    abstract away authentication first so it is much CLEARER.
    141130
    142 [ ] automated testing -- "Windmill seems to be more popular now -- especially with Python stuff "
    143131
    144132[ ] find a way to provide same info as data directory but without making it super-permissive.
    145133    Maybe I can make an api for getting files from a data location or something...
     
    483471
    484472[x] When saving a worksheet, the default filename has "..." in it.
    485473
     474[x] add message to the top of each *old* sage notebook .py file
     475 stating that one should work on sagenb instead.  This is a patch to
     476 the core Sage library.
     477
     478[x] fix all doctests in sagenb code and make a patch against core
     479sage library that imports enough of sagenb by default so I can
     480run all these doctests. 
     481
     482[x] rate a worksheet -- note that the top of the browser (title) says
     483error, though in fact there is no error.
     484
     485[x] change to 100% html format for worksheets.
     486
     487[x] notebook docs -- something in "doc/en/sagenb"
     488
     489[x] automated testing -- "Windmill seems to be more popular now -- especially with Python stuff "
  • sass/src/_topbar.sass

    diff --git a/sass/src/_topbar.sass b/sass/src/_topbar.sass
    a b  
    8787
    8888
    8989div
    90   &#user-controls
     90  &#user-main-controls
    9191    +clearfix
    9292    :clear both
    9393    :border-bottom 1px solid #c9d7f1
  • new file sass/src/_worksheet_listing.sass

    diff --git a/sass/src/_worksheet_listing.sass b/sass/src/_worksheet_listing.sass
    new file mode 100644
    - +  
     1/************ User Home (Worksheet listing) **************************/
     2
     3#worksheet-listing-page
     4  #welcome-message
     5    :text-align center
     6    :padding 1em
     7
     8.ratingmsg
     9  :color #112abb
     10  :padding 0.3em
     11  :font-size 14px
     12
     13.pubmsg
     14  :font-family sans-serif
     15  :color #112abb
     16  :padding 0.3em
     17  :font-size 12px
     18
     19#worksheet-list
     20  :clear both
     21  :width 100%
     22  thead
     23    :background-color #e8eef7
     24  td.checkbox
     25    :padding 4px
     26
     27.controls a, .usercontrol
     28  :color #112abb
     29  :font-size 14px
     30  :text-decoration underline
     31
     32  &:hover
     33    :cursor pointer
     34
     35.controls
     36  span
     37    :color #112abb
     38    :padding 0.3em
     39    :font-size 14px
     40
     41
     42.user-controls a, .boldusercontrol
     43  :color #112abb
     44  :font-weight bold
     45  :font-size 14px
     46
     47.user-controls a, .controls a, .controls span
     48  :padding 0.3em
     49
     50a
     51  &.control, &.control-select
     52    :background-color #7799bb
     53    :font-family sans-serif
     54    :color #ffffff
     55    :padding-top 0.25em
     56    :padding-bottom 0.25em
     57    :padding-left 0.5em
     58    :padding-right 0.5em
     59    :font-size 15px
     60    :font-weight bold
     61    :text-decoration none
     62
     63  &.control:hover
     64    :cursor pointer
     65
     66  &.control-select
     67    :background-color #4477aa
     68
     69    &:hover
     70      :cursor pointer
     71
     72
     73.sharebar
     74  :background-color #4477aa
     75  :font-family sans-serif
     76  :color #ffffff
     77  :padding-top 0.5em
     78  :padding-bottom 0.5em
     79  :padding-left 2em
     80  :font-size 1.25em
     81  :font-weight bold
     82
     83
     84textarea.edit
     85  :font-family courier, monospace
     86  :font-size 10pt
     87  :border 1px solid #8cacbb
     88  :color black
     89  :background-color white
     90  :padding 3px
     91  :overflow auto
     92  :margin-top 0.5em
     93
     94
     95a.listcontrol
     96  :padding 1ex
     97  :color #112abb
     98  :font-weight bold
     99  :font-size 14px
     100  :text-decoration none
     101
     102
     103hr
     104  &.usercontrol
     105    :border 0
     106    :width 99%
     107    :color #c9d7f1
     108    :background-color #c9d7f1
     109    :height 1px
     110
     111  &.greybar hr.negative_greybar
     112    :border 0
     113    :width 99%
     114    :color #aaa
     115    :background-color #aaa
     116    :height 1px
     117
     118  &.negative_greybar
     119    :top -1em
     120    :position relative
     121
     122
     123span
     124  &.checkcol
     125    :position relative
     126    :left 0%
     127    :width 10%
     128
     129  &.leftcol
     130    :position relative
     131    :left 10%
     132    :width 20%
     133
     134  &.middlecol
     135    :position relative
     136    :left 30%
     137    :width 20%
     138
     139  &.rightcol
     140    :position relative
     141    :left 50%
     142    :width 20%
     143
     144
     145tr.greybox
     146  :background-color #e8eef7
     147
     148
     149td.entry
     150  :padding 4px
     151
     152
     153div.thinspace
     154  :border 0
     155  :height 2px
     156
     157
     158tr.thingreybox
     159  :background-color #aaa
     160
     161
     162div.ultrathinspace
     163  :border 0
     164  :height 0px
     165
     166
     167.lastedit
     168  :font-family sans-serif
     169  :font-size 10px
     170  :color #717171
     171
     172.revs
     173  :font-family sans-serif
     174  :font-size 12px
     175  :font-weight bold
     176  :color #333333
     177
     178.users
     179  :font-family sans-serif
     180  :font-size 13px
     181  :color #222222
     182
     183
     184a.share
     185  :font-family sans-serif
     186  :font-size 10px
     187  :color #7777cc
     188
     189
     190select
     191  &.worksheet
     192    :width 6em
     193    :border #aaaaaa
     194    :border-style solid
     195    :border-top-width 1px
     196    :border-right-width 1px
     197    :border-bottom-width 1px
     198    :border-left-width 1px
     199
     200  &.worksheet_list, &.worksheet_edit
     201    :width 5em
     202    :border #aaaaaa
     203    :border-style solid
     204    :border-top-width 1px
     205    :border-right-width 1px
     206    :border-bottom-width 1px
     207    :border-left-width 1px
     208
     209
     210td
     211  &.worksheet_link
     212    :font-family sans-serif
     213    :font-size 12px
     214    :font-weight bold
     215    :color #000000
     216
     217  &.archived_worksheet_link, &.owner_collab, &.last_edited
     218    :font-family sans-serif
     219    :font-size 12px
     220    :color #000000
     221
     222
     223span.addtext
     224  :font-family sans-serif
     225  :font-size 13px
     226  :color #222
     227
     228
     229textarea.plaintextedit
     230  :font-family courier, monospace
     231  :font-size 10pt
     232  :border 1px solid #8cacbb
     233  :color black
     234  :background-color white
     235  :overflow auto
     236  :width 99%
     237  :height 60%
     238
     239
     240pre.plaintext
     241  :overflow auto
     242  :font-family courier, monospace
     243  :font-size 10pt
     244  :border 1px solid #8cacbb
     245  :color black
     246  :background-color white
     247  :margin-top 0.5em
     248
     249
     250div.docidx
     251  :text-align center
     252  :font-family sans-serif
     253  :font-size 16px
     254  :color #222
     255  :font-weight bold
     256
     257
     258span
     259  &.ping
     260    :display none
     261
     262  &.pingdown
     263    :font-family sans-serif
     264    :font-size 15px
     265    :font-weight bold
     266    :color white
     267    :background-color #990000
     268    :margin-left 1em
  • sass/src/main.sass

    diff --git a/sass/src/main.sass b/sass/src/main.sass
    a b  
    11841184  :position relative
    11851185  :top -20ex
    11861186  :right 0ex
    1187 
     1187t
    11881188
    11891189.thin-right
    11901190  :position absolute
     
    11921192  :right 0
    11931193  :width 70%
    11941194
    1195 /************ User Home (Worksheet listing) **************************/
    1196 
    1197 .ratingmsg
    1198   :color #112abb
    1199   :padding 0.3em
    1200   :font-size 14px
    1201 
    1202 .pubmsg
    1203   :font-family sans-serif
    1204   :color #112abb
    1205   :padding 0.3em
    1206   :font-size 12px
    1207 
    1208 #worksheet-list
    1209   :clear both
    1210   :width 100%
    1211   thead
    1212     :background-color #e8eef7
    1213   td.checkbox
    1214     :padding 4px
    1215 
    1216 .controls a, .usercontrol
    1217   :color #112abb
    1218   :font-size 14px
    1219   :text-decoration underline
    1220 
    1221   &:hover
    1222     :cursor pointer
    1223 
    1224 .controls
    1225   span
    1226     :color #112abb
    1227     :padding 0.3em
    1228     :font-size 14px
    1229 
    1230 
    1231 .user-controls a, .boldusercontrol
    1232   :color #112abb
    1233   :font-weight bold
    1234   :font-size 14px
    1235 
    1236 .user-controls a, .controls a, .controls span
    1237   :padding 0.3em
    1238 
    1239 a
    1240   &.control, &.control-select
    1241     :background-color #7799bb
    1242     :font-family sans-serif
    1243     :color #ffffff
    1244     :padding-top 0.25em
    1245     :padding-bottom 0.25em
    1246     :padding-left 0.5em
    1247     :padding-right 0.5em
    1248     :font-size 15px
    1249     :font-weight bold
    1250     :text-decoration none
    1251 
    1252   &.control:hover
    1253     :cursor pointer
    1254 
    1255   &.control-select
    1256     :background-color #4477aa
    1257 
    1258     &:hover
    1259       :cursor pointer
    1260 
    1261 
    1262 .sharebar
    1263   :background-color #4477aa
    1264   :font-family sans-serif
    1265   :color #ffffff
    1266   :padding-top 0.5em
    1267   :padding-bottom 0.5em
    1268   :padding-left 2em
    1269   :font-size 1.25em
    1270   :font-weight bold
    1271 
    1272 
    1273 textarea.edit
    1274   :font-family courier, monospace
    1275   :font-size 10pt
    1276   :border 1px solid #8cacbb
    1277   :color black
    1278   :background-color white
    1279   :padding 3px
    1280   :overflow auto
    1281   :margin-top 0.5em
    1282 
    1283 
    1284 a.listcontrol
    1285   :padding 1ex
    1286   :color #112abb
    1287   :font-weight bold
    1288   :font-size 14px
    1289   :text-decoration none
    1290 
    1291 
    1292 hr
    1293   &.usercontrol
    1294     :border 0
    1295     :width 99%
    1296     :color #c9d7f1
    1297     :background-color #c9d7f1
    1298     :height 1px
    1299 
    1300   &.greybar hr.negative_greybar
    1301     :border 0
    1302     :width 99%
    1303     :color #aaa
    1304     :background-color #aaa
    1305     :height 1px
    1306 
    1307   &.negative_greybar
    1308     :top -1em
    1309     :position relative
    1310 
    1311 
    1312 span
    1313   &.checkcol
    1314     :position relative
    1315     :left 0%
    1316     :width 10%
    1317 
    1318   &.leftcol
    1319     :position relative
    1320     :left 10%
    1321     :width 20%
    1322 
    1323   &.middlecol
    1324     :position relative
    1325     :left 30%
    1326     :width 20%
    1327 
    1328   &.rightcol
    1329     :position relative
    1330     :left 50%
    1331     :width 20%
    1332 
    1333 
    1334 tr.greybox
    1335   :background-color #e8eef7
    1336 
    1337 
    1338 td.entry
    1339   :padding 4px
    1340 
    1341 
    1342 div.thinspace
    1343   :border 0
    1344   :height 2px
    1345 
    1346 
    1347 tr.thingreybox
    1348   :background-color #aaa
    1349 
    1350 
    1351 div.ultrathinspace
    1352   :border 0
    1353   :height 0px
    1354 
    1355 
    1356 .lastedit
    1357   :font-family sans-serif
    1358   :font-size 10px
    1359   :color #717171
    1360 
    1361 .revs
    1362   :font-family sans-serif
    1363   :font-size 12px
    1364   :font-weight bold
    1365   :color #333333
    1366 
    1367 .users
    1368   :font-family sans-serif
    1369   :font-size 13px
    1370   :color #222222
    1371 
    1372 
    1373 a.share
    1374   :font-family sans-serif
    1375   :font-size 10px
    1376   :color #7777cc
    1377 
    1378 
    1379 select
    1380   &.worksheet
    1381     :width 6em
    1382     :border #aaaaaa
    1383     :border-style solid
    1384     :border-top-width 1px
    1385     :border-right-width 1px
    1386     :border-bottom-width 1px
    1387     :border-left-width 1px
    1388 
    1389   &.worksheet_list, &.worksheet_edit
    1390     :width 5em
    1391     :border #aaaaaa
    1392     :border-style solid
    1393     :border-top-width 1px
    1394     :border-right-width 1px
    1395     :border-bottom-width 1px
    1396     :border-left-width 1px
    1397 
    1398 
    1399 td
    1400   &.worksheet_link
    1401     :font-family sans-serif
    1402     :font-size 12px
    1403     :font-weight bold
    1404     :color #000000
    1405 
    1406   &.archived_worksheet_link, &.owner_collab, &.last_edited
    1407     :font-family sans-serif
    1408     :font-size 12px
    1409     :color #000000
    1410 
    1411 
    1412 span.addtext
    1413   :font-family sans-serif
    1414   :font-size 13px
    1415   :color #222
    1416 
    1417 
    1418 textarea.plaintextedit
    1419   :font-family courier, monospace
    1420   :font-size 10pt
    1421   :border 1px solid #8cacbb
    1422   :color black
    1423   :background-color white
    1424   :overflow auto
    1425   :width 99%
    1426   :height 60%
    1427 
    1428 
    1429 pre.plaintext
    1430   :overflow auto
    1431   :font-family courier, monospace
    1432   :font-size 10pt
    1433   :border 1px solid #8cacbb
    1434   :color black
    1435   :background-color white
    1436   :margin-top 0.5em
    1437 
    1438 
    1439 div.docidx
    1440   :text-align center
    1441   :font-family sans-serif
    1442   :font-size 16px
    1443   :color #222
    1444   :font-weight bold
    1445 
    1446 
    1447 span
    1448   &.ping
    1449     :display none
    1450 
    1451   &.pingdown
    1452     :font-family sans-serif
    1453     :font-size 15px
    1454     :font-weight bold
    1455     :color white
    1456     :background-color #990000
    1457     :margin-left 1em
    1458 
     1195@import worksheet_listing.sass
    14591196@import prettify.sass
    14601197@import source.sass
    14611198@import print_worksheet.sass