Ticket #11459: trac11459_rst2notebook_sagenb-sl.patch

File trac11459_rst2notebook_sagenb-sl.patch, 59.3 KB (added by slabbe, 11 years ago)

Applies on the new flask sagenb repository

  • flask_version/worksheet_listing.py

    # HG changeset patch
    # User Sebastien Labbe <slabqc at gmail.com>
    # Date 1308369592 25200
    # Node ID ef51b01fd7bc9fb4dbfeefada98cfd73c50366c2
    # Parent  b732dafbff2259938b55873e247213f9a82fe9e3
    #11459: ReST -> Sage worksheet
    
    diff --git a/flask_version/worksheet_listing.py b/flask_version/worksheet_listing.py
    a b def upload_worksheet(): 
    232232        # to a temporary file with the same extension
    233233        path = urlparse.urlparse(url).path
    234234        extension = os.path.splitext(path)[1].lower()
    235         if extension not in [".txt", ".sws", ".zip", ".html"]:
     235        if extension not in [".txt", ".sws", ".zip", ".html", ".rst"]:
    236236            # Or shall we try to import the document as an sws in doubt?
    237237            return current_app.message("Unknown worksheet extension: %s. %s" % (extension, backlinks))
    238238        filename = tmp_filename()+extension
    def upload_worksheet(): 
    268268                W = g.notebook.import_worksheet(filename, g.username)
    269269
    270270        except Exception, msg:
     271            print "Error: %s" % msg
    271272            s = 'There was an error uploading the worksheet.  It could be an old unsupported format or worse.  If you desperately need its contents contact the <a href="http://groups.google.com/group/sage-support">sage-support group</a> and post a link to your worksheet.  Alternatively, an sws file is just a bzip2 tarball; take a look inside!%s' % backlinks
    272273            return current_app.message(s, url_for('home', username=g.username))
    273274        finally:
  • sagenb/data/sage/html/upload.html

    diff --git a/sagenb/data/sage/html/upload.html b/sagenb/data/sage/html/upload.html
    a b  
    88
    99<div>
    1010    <h2>Upload worksheet to the Sage Notebook</h2>
    11     <p>Supported file formats: sws, html, or txt, or zip archive of such.</p>
    12 
     11    <p>Supported file formats:</p>
     12    <ul class="simple">
     13    <li><tt>.sws</tt> - a Sage worksheet</li>
     14    <li><tt>.html</tt> or <tt>.txt</tt> - a worksheet text file with html code and cells surrounded by <tt>&#123;&#123;&#123;</tt> and <tt>&#125;&#125;&#125;</tt> that defines a worksheet</li>
     15    <li><tt>.html</tt> - the URL of a page of the Sage Documentation, for example the URL of <a class="reference external" href="http://www.sagemath.org/doc/reference/sage/rings/integer.html">this page</a></li>
     16    <li><tt>.html</tt> - an HTML page generated by docutils from a ReStructuredText file</li>
     17    <li><tt>.rst</tt> - a ReStructuredText file (Add "<tt>.. escape-backslashes</tt>" as a line in the file if you want backslashes to be escaped. Put latex code inside backticks "<tt>`</tt>" or dollar signs "<tt>$</tt>" or "<tt>$$</tt>". Math role is not supported for now.)</li>
     18    <li><tt>.zip</tt> - a zip archive of any of the above</li>
     19    </ul>
    1320    <form method="POST" action="upload_worksheet"
    1421          name="upload" enctype="multipart/form-data">
    1522        <div>
    16             <label for="file">Browse your computer to select a worksheet file to upload:</label>
     23            <label for="file">Browse your computer to select a file to upload:</label>
    1724            <input size="50" type="file" name="file" />
    1825        </div>
    1926        <div>
    20             <label for="url">Or enter the URL of a worksheet file on the web:</label>
     27            <label for="url">Or enter the URL of a file on the web:</label>
    2128            <input size="50" type="text" name="url" />
    2229        </div>
    2330        <div>
  • sagenb/notebook/docHTMLProcessor.py

    diff --git a/sagenb/notebook/docHTMLProcessor.py b/sagenb/notebook/docHTMLProcessor.py
    a b  
    22"""
    33Live Documentation in the Notebook
    44
    5 Processes Sage documentation into notebook worksheet format with
    6 evaluable examples.
     5Conversion of HTML (output by Sphinx or docutils) to Sage worksheet txt
     6file.
    77
    8 This takes in any HTML document, i.e., Sage documentation, and returns
    9 it in the editable format (like the notebook edit window). It also
    10 returns a string representing the CSS link for the document.  The SGML
    11 parser is setup to return only the body of the HTML documentation page
    12 and to re-format Sage examples and type-setting.
     8This takes an HTML document, i.e., Sage documentation, and returns it in
     9the editable format (notebook worksheet format with evaluable examples). It
     10also returns a string representing the CSS link for the document.  The SGML
     11parser is setup to return only the body of the HTML documentation page and
     12to re-format Sage examples and type-setting.
    1313
    14 Note: This extension of sgmllib.SGMLParser was partly inspired by Mark
    15 Pilgrim's 'Dive Into Python' examples.
     14This module contains three classes:
    1615
    17 Author:
     16- :class:``sagenb.notebook.docHTMLProcessor.genericHTMLProcessor`` :
     17  gathers all the common methods of the other two classes.
     18
     19- :class:``sagenb.notebook.docHTMLProcessor.SphinxHTMLProcessor`` :
     20  translates HTML file generated by Sphinx into a worksheet text file
     21
     22- :class:``sagenb.notebook.docHTMLProcessor.docutilsHTMLProcessor``
     23  translates HTML file generated by docutils ``rst2html`` command into a
     24  worksheet text file
     25
     26.. NOTE::
     27
     28    This extension of sgmllib.SGMLParser was partly inspired by Mark
     29    Pilgrim's 'Dive Into Python' examples.
     30
     31AUTHORS:
    1832
    1933- Dorian Raymer (2006): first version
    2034
    2135- William Stein (2007-06-10): rewrite to work with twisted Sage notebook
    2236
    2337- Mike Hansen (2008-09-27): Rewrite to work with Sphinx HTML documentation
     38
     39- Sebastien Labbe (2011-01-15): Added a new class named
     40  docutilsHTMLProcessor used for translating the html output of the
     41  rst2html docutils command run on a rst file into worksheet text file.
     42  Also added a new class named genericHTMLProcessor which gathers the
     43  common methods of both docutilsHTMLProcessor and SphinxHTMLProcessor
     44  classes. Added lots of doctests to make its coverage 100% doctested.
     45
     46EXAMPLES:
     47
     48Process the output of docutils ``rst2html`` command::
     49
     50    sage: rst = ""
     51    sage: rst += "Additions in Sage\n"
     52    sage: rst += "-----------------\n"
     53    sage: rst += "\n"
     54    sage: rst += "Let's do easy computations with Sage::\n"
     55    sage: rst += "\n"
     56    sage: rst += "    s" + "age: 4 + 3\n"
     57    sage: rst += "    7\n"
     58    sage: rst += "    s" + "age: 1 - 2\n"
     59    sage: rst += "    -1\n"
     60    sage: rst += "\n"
     61    sage: rst += "Let's do `x^2`::\n"
     62    sage: rst += "\n"
     63    sage: rst += "    s" + "age: x^2\n"
     64    sage: rst += "    x^2\n"
     65    sage: from docutils.core import publish_string
     66    sage: html = publish_string(rst, writer_name='html')
     67    sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     68    sage: p = docutilsHTMLProcessor()
     69    sage: txt = p.process_doc_html(html)
     70    sage: len(txt)
     71    191
     72    sage: print txt
     73    <h1 class="title">Additions in Sage</h1>
     74    <BLANKLINE>
     75    <BLANKLINE>
     76    <BLANKLINE>
     77    <p>Let's do easy computations with Sage:</p>
     78    <BLANKLINE>
     79    {{{id=0|
     80    4 + 3
     81    ///
     82    7
     83    }}}
     84    <BLANKLINE>
     85    {{{id=1|
     86    1 - 2
     87    ///
     88    -1
     89    }}}
     90    <BLANKLINE>
     91    <p>Let's do $x^2$:</p>
     92    <BLANKLINE>
     93    {{{id=2|
     94    x^2
     95    ///
     96    x^2
     97    }}}
     98    <BLANKLINE>
     99    <BLANKLINE>
    24100"""
    25101#############################################################################
    26102#       Copyright (C) 2007 William Stein <wstein@gmail.com> and Dorian Raimer
     103#       Copyright (C) 2011 Sebastien Labbe <slabqc at gmail.com>
    27104#  Distributed under the terms of the GNU General Public License (GPL)
    28105#  The full text of the GPL is available at:
    29106#                  http://www.gnu.org/licenses/
    from sgmllib import SGMLParser 
    33110from urllib import splittag
    34111from htmlentitydefs import entitydefs
    35112
    36 class SphinxHTMLProcessor(SGMLParser):
    37     def reset(self):
    38         """
    39         Initialize necessary variables.  Called by
    40         :meth:`SGMLParser.__init__`.
    41 
    42         EXAMPLES::
    43 
    44             sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
    45             sage: d = SphinxHTMLProcessor()
    46             sage: d.bodyQ
    47             False
    48             sage: d.in_highlight_div
    49             False
    50             sage: d.temp_pieces
    51             []
    52             sage: d.all_pieces
    53             ''
    54             sage: d.cellcount
    55             0
    56         """
    57         # flags
    58         self.bodyQ = False #don't keep anything before the <body> tag
    59         self.in_highlight_div = False
    60 
    61         # lists of what the parser keeps
    62         self.temp_pieces = []
    63         self.all_pieces = ''
    64 
    65         # counters
    66         self.cellcount = 0
    67                
    68         SGMLParser.reset(self)
    69 
     113class genericHTMLProcessor(SGMLParser):
     114    r"""
     115    This class gathers the methods that are common to both classes
     116    :class:`sagenb.notebook.SphinxHTMLProcessor` and
     117    :class:`sagenb.notebook.docutilsHTMLProcessor` .
     118    """
    70119    def process_doc_html(self, doc_in):
    71120        """
    72121        Returns processed HTML input as HTML output.  This is the only
    class SphinxHTMLProcessor(SGMLParser): 
    79128        OUTPUT:
    80129
    81130        - a string; the processed HTML
     131
     132        EXAMPLES::
     133
     134            sage: rst = ""
     135            sage: rst += "Title\n"
     136            sage: rst += "-----\n"
     137            sage: rst += "n"
     138            sage: rst += "Some text\n"
     139            sage: from docutils.core import publish_string
     140            sage: html = publish_string(rst, writer_name='html')
     141            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     142            sage: p = docutilsHTMLProcessor()
     143            sage: txt = p.process_doc_html(html)
     144            sage: len(txt)
     145            51
     146            sage: txt
     147            '<h1 class="title">Title</h1>\n\n<p>nSome text</p>\n\n\n\n'
     148
    82149        """       
    83150        # self.feed() is a SGMLParser method and starts everything
    84151        # off; Most of the functions here are extensions to
    class SphinxHTMLProcessor(SGMLParser): 
    86153        self.feed(doc_in) #SGMLParser call
    87154        self.close()     #SGMLParser call
    88155        self.hand_off_temp_pieces('to_doc_pieces')
    89         self.all_pieces = self.all_pieces[:-16]  # drop </body></html>
    90156        return self.all_pieces
    91157
    92        
     158
    93159    def hand_off_temp_pieces(self, piece_type):
    94160        """
    95161        To separate the documentation's content from the Sage
    class SphinxHTMLProcessor(SGMLParser): 
    100166        INPUT:
    101167
    102168        - ``piece_type`` - a string; indicates the type of and how to
    103           process the current ``self.temp_pieces``
     169          process the current ``self.temp_pieces``. It can be one of the
     170          following:
     171
     172          - ``"to_doc_pieces"`` - put temp_pieces in all_pieces
     173          - ``"ignore"`` - delete temp_pieces
     174          - ``"to_cell_pieces"`` - translate temp_pieces into cells and put
     175            it in all_pieces
     176
     177        EXAMPLES:
     178
     179        Move temporary pieces to all pieces::
     180
     181            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     182            sage: p = docutilsHTMLProcessor()
     183            sage: p.all_pieces = 'a lot of stuff done '
     184            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     185            sage: p.hand_off_temp_pieces('to_doc_pieces')
     186            sage: p.all_pieces
     187            'a lot of stuff done bunch of tmp strings'
     188            sage: p.temp_pieces
     189            []
     190
     191        Ignore temporary pieces::
     192
     193            sage: p = docutilsHTMLProcessor()
     194            sage: p.all_pieces = 'a lot of stuff done '
     195            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     196            sage: p.hand_off_temp_pieces('ignore')
     197            sage: p.all_pieces
     198            'a lot of stuff done '
     199            sage: p.temp_pieces
     200            []
     201
     202        Translate temporary pieces (starting with sage prompt) into cells::
     203
     204            sage: p = docutilsHTMLProcessor()
     205            sage: p.all_pieces = 'a lot of stuff done '
     206            sage: p.temp_pieces = ['sage'+': 4+4\n', '8\n', 'sage'+': 9-4\n', '5\n']
     207            sage: p.hand_off_temp_pieces('to_cell_pieces')
     208            sage: print p.all_pieces
     209            a lot of stuff done
     210            {{{id=0|
     211            4+4
     212            ///
     213            8
     214            }}}
     215            <BLANKLINE>
     216            {{{id=1|
     217            9-4
     218            ///
     219            5
     220            }}}
     221            sage: p.temp_pieces
     222            []
     223
     224        Translate temporary pieces (not starting with sage prompt) into cells::
     225
     226            sage: p = docutilsHTMLProcessor()
     227            sage: p.all_pieces = 'a lot of stuff done '
     228            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     229            sage: p.hand_off_temp_pieces('to_cell_pieces')
     230            sage: print p.all_pieces
     231            a lot of stuff done <pre class="literal-block">
     232            bunch of tmp strings
     233            </pre>
     234            sage: p.temp_pieces
     235            []
     236
    104237        """
    105238        pieces = "".join(self.temp_pieces)
    106239        pieces = pieces.lstrip()
    class SphinxHTMLProcessor(SGMLParser): 
    109242            self.temp_pieces = []
    110243        elif piece_type == 'ignore':
    111244            self.temp_pieces = []
    112         else:
     245        elif piece_type == 'to_cell_pieces':
    113246            pieces = self.process_cell_input_output(pieces)
    114247            self.all_pieces += pieces
    115248            self.temp_pieces = []
     249        else:
     250            raise ValueError('unknown piece_type(=%s)' % piece_type)
    116251
    117252    def get_cellcount(self):
    118253        """
    class SphinxHTMLProcessor(SGMLParser): 
    124259
    125260        EXAMPLES::
    126261
     262            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     263            sage: d = docutilsHTMLProcessor()
     264            sage: d.get_cellcount()
     265            0
     266            sage: d.get_cellcount()
     267            1
     268
     269        ::
     270
    127271            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
    128272            sage: d = SphinxHTMLProcessor()
    129273            sage: d.get_cellcount()
    class SphinxHTMLProcessor(SGMLParser): 
    138282        """
    139283        Process and return a ``cell_piece``.
    140284
    141         All divs with CSS class="highlight" contain code examples.
    142         They include
     285        All divs with CSS class="highlight" (if generated with Sphinx)  or
     286        class="literal-block" (if generated with docutils) contain code
     287        examples.  They include
    143288
    144289        - Models of how the function works.  These begin with, e.g.,
    145290          'INPUT:' and are re-styled as divs with
    class SphinxHTMLProcessor(SGMLParser): 
    156301        OUTPUT:
    157302
    158303        - a string; the processed cell piece
     304
     305        EXAMPLES::
     306
     307            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     308            sage: p = docutilsHTMLProcessor()
     309            sage: s = "s" + "age: 4 + 4\n8"    # avoid the doctest script to parse "sage:"
     310            sage: p.process_cell_input_output(s)
     311            '\n{{{id=0|\n4 + 4\n///\n8\n}}}\n\n'
     312            sage: print p.process_cell_input_output(s)
     313            {{{id=1|
     314            4 + 4
     315            ///
     316            8
     317            }}}
     318
     319        ::
     320
     321            sage: s = "age: 4 + 4\n8"
     322            sage: print p.process_cell_input_output(s)
     323            <pre class="literal-block">
     324            age: 4 + 4
     325            8
     326            </pre>
     327
     328        ::
     329
     330            sage: s = '&gt;'*3 + " 4 + 4\n8"
     331            sage: print p.process_cell_input_output(s)
     332            {{{id=2|
     333            4 + 4
     334            ///
     335            8
     336            }}}
     337
     338        ::
     339
     340            sage: s = "s" + "age: 4 + 4\n8\ns" + "age: 2 + 2\n4"
     341            sage: print p.process_cell_input_output(s)
     342            {{{id=3|
     343            4 + 4
     344            ///
     345            8
     346            }}}
     347            <BLANKLINE>
     348            {{{id=4|
     349            2 + 2
     350            ///
     351            4
     352            }}}
    159353        """
    160354        if cell_piece[:5] != 'sage:' and cell_piece[:12] != '&gt;'*3:
    161             piece = '<div class="highlight"><pre>'
    162             piece += cell_piece
    163             piece = piece.replace('{','{&nbsp;')
    164             piece = piece.replace('}','}&nbsp;')
    165             piece += '</pre></div>'
     355            piece = self.false_positive_input_output_cell(cell_piece)
    166356        else:
    167357            # group and format inputs and outputs
    168358            pieces = cell_piece.split('\n')
    169359            output_flag = False
    170             piece = '{{{id=%s|\n'%self.get_cellcount()
     360            piece = '\n{{{id=%s|\n'%self.get_cellcount()
    171361            for p in pieces:
    172362
    173363                if p[:5] == 'sage:' and not output_flag:
    174364                    piece += p[5:].lstrip() + '\n'
    175365                elif p[:5] == 'sage:' and output_flag:
    176                     piece += '}}}\n{{{id=%s|\n'%self.get_cellcount() + p[5:].lstrip() + '\n'
     366                    piece += '\n}}}\n\n{{{id=%s|\n'%self.get_cellcount() + p[5:].lstrip() + '\n'
    177367                    output_flag = False
    178368                elif p[:12] == '&gt;'*3 and not output_flag:
    179369                    piece += p[12:].lstrip() + '\n'
    180370                elif p[:12] == '&gt;'*3 and output_flag:
    181                     piece += '}}}\n{{{id=%s|\n'%self.get_cellcount() + p[12:].lstrip() + '\n'
     371                    piece += '\n}}}\n\n{{{id=%s|\n'%self.get_cellcount() + p[12:].lstrip() + '\n'
    182372                    output_flag = False
    183373                elif p[:3] == '...':
    184374                    piece += p[3:] + '\n'
    class SphinxHTMLProcessor(SGMLParser): 
    192382                    # first occurrence of an output string
    193383                    # write /// denoting output
    194384                    if output_flag == False:
    195                         piece += '///\n'
    196                         piece += p + '\n'
     385                        piece += '///'
     386                        if p:
     387                            piece += '\n' + p
    197388                        output_flag = True
    198389                    # multiple output lines exist, don't need /// repeated
    199390                    else:
    200                         piece += p + '\n'
    201             piece += '}}}\n'
     391                        piece += p
     392            piece += '\n}}}\n\n'
    202393        return piece
    203394               
    204395    ##############################################
    205396    ## General tag handlers
    206     ## These just append their HTML to
    207     ## self.temp_pieces.
    208    
     397    ## These just append their HTML to self.temp_pieces.
    209398    def unknown_starttag(self, tag, attrs):
    210         if self.bodyQ:
     399        r"""
     400        INPUT:
     401
     402        - ``tag`` - string
     403        - ``attrs`` - list of tuples
     404
     405        EXAMPLES::
     406
     407            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     408            sage: p = docutilsHTMLProcessor()
     409            sage: p.all_pieces = 'a lot of stuff done '
     410            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     411            sage: p.keep_data = True
     412            sage: tag = 'style'
     413            sage: attrs = [('type', 'text/css')]
     414            sage: p.unknown_starttag(tag, attrs)
     415            sage: p.all_pieces
     416            'a lot of stuff done '
     417            sage: p.temp_pieces
     418            ['bunch ', 'of ', 'tmp ', 'strings', '<style type="text/css">']
     419        """
     420        if self.keep_data:
    211421            strattrs = "".join([' %s="%s"' % (key, value) for key, value in attrs])
    212422            self.temp_pieces.append("<%(tag)s%(strattrs)s>" % locals())
    213423
    214424    def unknown_endtag(self, tag):
    215         if self.bodyQ:
     425        r"""
     426        INPUT:
     427
     428        - ``tag`` - string
     429
     430        EXAMPLES::
     431
     432            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     433            sage: p = docutilsHTMLProcessor()
     434            sage: p.all_pieces = 'a lot of stuff done '
     435            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     436            sage: p.keep_data = True
     437            sage: p.unknown_endtag('head')
     438            sage: p.all_pieces
     439            'a lot of stuff done '
     440            sage: p.temp_pieces
     441            ['bunch ', 'of ', 'tmp ', 'strings', '</head>']
     442        """
     443        if self.keep_data:
    216444            self.temp_pieces.append("</%(tag)s>" % locals())
    217445
    218446    def handle_data(self, data):
    219         if self.bodyQ:
     447        r"""
     448        INPUT:
     449
     450        - ``data`` - string
     451
     452        EXAMPLES::
     453
     454            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     455            sage: p = docutilsHTMLProcessor()
     456            sage: p.all_pieces = 'a lot of stuff done '
     457            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     458            sage: p.keep_data = True
     459            sage: p.handle_data('some important data')
     460            sage: p.all_pieces
     461            'a lot of stuff done '
     462            sage: p.temp_pieces
     463            ['bunch ', 'of ', 'tmp ', 'strings', 'some important data']
     464        """
     465        if self.keep_data:
    220466            self.temp_pieces.append(data)
    221    
    222467    def handle_charref(self, ref):
    223         if self.bodyQ:
     468        r"""
     469        INPUT:
     470
     471        - ``ref`` - string
     472
     473        EXAMPLES::
     474
     475            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     476            sage: p = docutilsHTMLProcessor()
     477            sage: p.all_pieces = 'a lot of stuff done '
     478            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     479            sage: p.keep_data = True
     480            sage: p.handle_charref('160')
     481            sage: p.all_pieces
     482            'a lot of stuff done '
     483            sage: p.temp_pieces
     484            ['bunch ', 'of ', 'tmp ', 'strings', '&#160;']
     485        """
     486        if self.keep_data:
    224487            self.temp_pieces.append("&#%(ref)s;" % locals())
    225488
    226489    def handle_entityref(self, ref):
    227         if self.bodyQ:
     490        r"""
     491        INPUT:
     492
     493        - ``ref`` - string
     494
     495        EXAMPLES::
     496
     497            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     498            sage: p = docutilsHTMLProcessor()
     499            sage: p.all_pieces = 'a lot of stuff done '
     500            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     501            sage: p.keep_data = True
     502            sage: p.handle_entityref('160')
     503            sage: p.all_pieces
     504            'a lot of stuff done '
     505            sage: p.temp_pieces
     506            ['bunch ', 'of ', 'tmp ', 'strings', '&160']
     507        """
     508        if self.keep_data:
    228509            self.temp_pieces.append("&%(ref)s" % locals())
    229510            if entitydefs.has_key(ref):
    230511                self.temp_pieces.append(';')
    231    
    232512    def handle_comment(self, data):             
    233         if self.bodyQ:
     513        r"""
     514        INPUT:
     515
     516        - ``data`` - string
     517
     518        EXAMPLES::
     519
     520            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     521            sage: p = docutilsHTMLProcessor()
     522            sage: p.all_pieces = 'a lot of stuff done '
     523            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     524            sage: p.keep_data = True
     525            sage: p.handle_comment('important comment')
     526            sage: p.all_pieces
     527            'a lot of stuff done '
     528            sage: p.temp_pieces
     529            ['bunch ', 'of ', 'tmp ', 'strings', '<!--important comment-->']
     530        """
     531        if self.keep_data:
    234532            self.temp_pieces.append("<!--%(data)s-->" % locals())
    235    
    236533    def handle_pi(self, text):
    237         if self.bodyQ:
     534        r"""
     535        Handle processing instructions
     536
     537        INPUT:
     538
     539        - ``text`` - string
     540
     541        EXAMPLES::
     542
     543            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     544            sage: p = docutilsHTMLProcessor()
     545            sage: p.all_pieces = 'a lot of stuff done '
     546            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     547            sage: p.keep_data = True
     548            sage: p.handle_pi('instructions')
     549            sage: p.all_pieces
     550            'a lot of stuff done '
     551            sage: p.temp_pieces
     552            ['bunch ', 'of ', 'tmp ', 'strings', '<?instructions>']
     553        """
     554        if self.keep_data:
    238555            self.temp_pieces.append("<?%(text)s>" % locals())
    239556
    240557    def handle_decl(self, text):
    241         if self.bodyQ:
     558        r"""
     559        INPUT:
     560
     561        - ``data`` - string
     562
     563        EXAMPLES::
     564
     565            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     566            sage: p = docutilsHTMLProcessor()
     567            sage: p.all_pieces = 'a lot of stuff done '
     568            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     569            sage: p.keep_data = True
     570            sage: p.handle_decl('declaration')
     571            sage: p.all_pieces
     572            'a lot of stuff done '
     573            sage: p.temp_pieces
     574            ['bunch ', 'of ', 'tmp ', 'strings', '<!declaration>']
     575        """
     576        if self.keep_data:
    242577            self.temp_pieces.append("<!%(text)s>" % locals())
    243578       
    244    
    245     #############################################
     579    ##############################################
    246580    ## Specific tag handlers
    247     ##
    248581    def start_body(self, attrs):
    249582        """
    250         Set ``self.bodyQ`` to True upon finding the opening body tag.
     583        Set ``self.keep_data`` to True upon finding the opening body tag.
    251584
    252585        INPUT:
    253586
    class SphinxHTMLProcessor(SGMLParser): 
    258591
    259592            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
    260593            sage: d = SphinxHTMLProcessor()
    261             sage: d.bodyQ
     594            sage: d.keep_data
    262595            False
    263596            sage: d.start_body(None)
    264             sage: d.bodyQ
     597            sage: d.keep_data
     598            True
     599
     600        ::
     601
     602            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     603            sage: d = docutilsHTMLProcessor()
     604            sage: d.keep_data
     605            False
     606            sage: d.start_body(None)
     607            sage: d.keep_data
    265608            True
    266609        """
    267         self.bodyQ = True
     610        self.keep_data = True
    268611
     612    def end_body(self):
     613        r"""
     614        EXAMPLES::
     615
     616            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     617            sage: p = docutilsHTMLProcessor()
     618            sage: p.all_pieces = 'a lot of stuff done '
     619            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     620            sage: p.end_body()
     621            sage: p.all_pieces
     622            'a lot of stuff done '
     623            sage: p.temp_pieces
     624            ['bunch ', 'of ', 'tmp ', 'strings']
     625        """
     626        pass
     627    def end_html(self):
     628        r"""
     629        INPUT:
     630
     631        - ``data`` - string
     632
     633        EXAMPLES::
     634
     635            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     636            sage: p = docutilsHTMLProcessor()
     637            sage: p.all_pieces = 'a lot of stuff done '
     638            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     639            sage: p.end_html()
     640            sage: p.all_pieces
     641            'a lot of stuff done '
     642            sage: p.temp_pieces
     643            ['bunch ', 'of ', 'tmp ', 'strings']
     644        """
     645        pass
     646
     647class SphinxHTMLProcessor(genericHTMLProcessor):
     648    def reset(self):
     649        """
     650        Initialize necessary variables.  Called by
     651        :meth:`SGMLParser.__init__`.
     652
     653        EXAMPLES::
     654
     655            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     656            sage: d = SphinxHTMLProcessor()    #indirect doctest
     657            sage: d.keep_data
     658            False
     659            sage: d.in_highlight_div
     660            False
     661            sage: d.temp_pieces
     662            []
     663            sage: d.all_pieces
     664            ''
     665            sage: d.cellcount
     666            0
     667        """
     668        # flags
     669        self.keep_data = False #don't keep anything before the <body> tag
     670        self.in_highlight_div = False
     671
     672        # lists of what the parser keeps
     673        self.temp_pieces = []
     674        self.all_pieces = ''
     675
     676        # counters
     677        self.cellcount = 0
     678               
     679        SGMLParser.reset(self)
     680
     681    def false_positive_input_output_cell(self, cell_piece):
     682        r"""
     683        Return the untouched html string of a false positive input output
     684        cell.
     685
     686        A false positive input-output cell come from a block of code which
     687        doesn't start with the sage prompt string 'sage:' or the Python
     688        prompt '>>>'.
     689
     690        INPUT:
     691
     692        - ``cell_piece`` - string, a cell piece
     693
     694        OUPUT:
     695
     696            string
     697
     698        EXAMPLES::
     699
     700            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     701            sage: p = SphinxHTMLProcessor()
     702            sage: s = "sage -rst2html -h"
     703            sage: print p.false_positive_input_output_cell(s)
     704            <div class="highlight"><pre>
     705            sage -rst2html -h
     706            </pre></div>
     707
     708        """
     709        piece = '<div class="highlight"><pre>\n'
     710        piece += cell_piece
     711        piece = piece.replace('{','{&nbsp;')
     712        piece = piece.replace('}','}&nbsp;')
     713        piece += '\n</pre></div>'
     714        return piece
     715
     716    #############################################
     717    ## Specific tag handlers
     718    ##
    269719    def start_div(self, attrs):
    270         #Find out if we are starting a highlighted div
     720        r"""
     721        Find out if we are starting a highlighted div.
     722
     723        Once we hit the <div> tag in a highlighted block,
     724        hand of all of the pieces we've encountered so far
     725        and ignore the tag.
     726       
     727        INPUT:
     728
     729        - ``attrs`` - list of tuple
     730
     731        EXAMPLES::
     732
     733            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     734            sage: p = SphinxHTMLProcessor()
     735            sage: p.all_pieces = 'a lot of stuff done '
     736            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     737            sage: attrs = [('class', 'highlight')]
     738            sage: p.start_div(attrs)
     739            sage: p.all_pieces
     740            'a lot of stuff done bunch of tmp strings'
     741            sage: p.temp_pieces
     742            []
     743            sage: p.in_highlight_div
     744            True
     745
     746        ::
     747
     748            sage: p = SphinxHTMLProcessor()
     749            sage: p.all_pieces = 'a lot of stuff done '
     750            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     751            sage: p.keep_data = True
     752            sage: attrs = [('class', 'something-else')]
     753            sage: p.start_div(attrs)
     754            sage: p.all_pieces
     755            'a lot of stuff done '
     756            sage: p.temp_pieces
     757            ['bunch ', 'of ', 'tmp ', 'strings', '<div class="something-else">']
     758            sage: p.in_highlight_div
     759            False
     760        """
    271761        for name, value in attrs:
    272762            if name.lower()=='class' and value.lower()=='highlight':
    273763                self.in_highlight_div = True
     764                self.hand_off_temp_pieces('to_doc_pieces')
    274765                return
    275766        self.unknown_starttag('div', attrs)
    276        
     767
    277768    def end_div(self):
    278         #Once we end the highlighted div, convert all of the pieces
    279         #to cells
     769        r"""
     770        Once we end the highlighted div, convert all of the pieces
     771        to cells.
     772
     773        EXAMPLES::
     774
     775            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     776            sage: p = SphinxHTMLProcessor()
     777            sage: p.all_pieces = 'a lot of stuff done '
     778            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings\n']
     779            sage: p.keep_data = True
     780            sage: attrs = [('class', 'highlight')]
     781            sage: p.start_div(attrs)
     782            sage: p.start_pre([])
     783            sage: sprompt = 'sa' + 'ge' + ': '    # to avoid problems with doctest script
     784            sage: p.handle_data('%s4+4\n8\n%sx^2\nx^2\n' % (sprompt, sprompt))
     785            sage: p.end_pre()
     786            sage: p.end_div()
     787            sage: print p.all_pieces
     788            a lot of stuff done bunch of tmp strings
     789            {{{id=0|
     790            4+4
     791            ///
     792            8
     793            }}}
     794            <BLANKLINE>
     795            {{{id=1|
     796            x^2
     797            ///
     798            x^2
     799            }}}
     800            sage: p.temp_pieces
     801            []
     802            sage: p.in_highlight_div
     803            False
     804
     805        ::
     806
     807            sage: p = SphinxHTMLProcessor()
     808            sage: p.all_pieces = 'a lot of stuff done '
     809            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     810            sage: p.keep_data = True
     811            sage: attrs = [('class', 'something-else')]
     812            sage: p.start_div(attrs)
     813            sage: p.handle_data('some data')
     814            sage: p.end_div()
     815            sage: print p.all_pieces
     816            a lot of stuff done
     817            sage: p.temp_pieces
     818            ['bunch ', 'of ', 'tmp ', 'strings', '<div class="something-else">', 'some data', '</div>']
     819            sage: p.in_highlight_div
     820            False
     821
     822        """
    280823        if self.in_highlight_div:
    281824            self.in_highlight_div = False
    282825            self.hand_off_temp_pieces('to_cell_pieces')
    class SphinxHTMLProcessor(SGMLParser): 
    284827        self.temp_pieces.append("</div>")
    285828   
    286829    def start_pre(self, attrs):
    287         #Once we hit the <pre> tag in a highlighted block,
    288         #hand of all of the pieces we've encountered so far
    289         #and ignore the tag.
     830        r"""
     831        Ignore tag <pre> when inside highligh div.
     832
     833        INPUT:
     834
     835        - ``attrs`` - list of tuple
     836
     837        EXAMPLES::
     838
     839            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     840            sage: p = SphinxHTMLProcessor()
     841            sage: p.all_pieces = 'a lot of stuff done '
     842            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     843            sage: p.keep_data = True
     844            sage: p.in_highlight_div = True
     845            sage: attrs = []
     846            sage: p.start_pre(attrs)
     847            sage: p.all_pieces
     848            'a lot of stuff done '
     849            sage: p.temp_pieces
     850            ['bunch ', 'of ', 'tmp ', 'strings']
     851
     852        ::
     853
     854            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     855            sage: p = SphinxHTMLProcessor()
     856            sage: p.all_pieces = 'a lot of stuff done '
     857            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     858            sage: p.keep_data = True
     859            sage: p.in_highlight_div = False
     860            sage: attrs = []
     861            sage: p.start_pre(attrs)
     862            sage: p.all_pieces
     863            'a lot of stuff done '
     864            sage: p.temp_pieces
     865            ['bunch ', 'of ', 'tmp ', 'strings', '<pre>']
     866        """
    290867        if self.in_highlight_div:
    291             self.hand_off_temp_pieces('to_doc_pieces')
    292868            return
    293869        self.unknown_starttag('pre',attrs)
    294870
    295871    def end_pre(self):
    296         #Ignore the pre tags in highlighted blocks
     872        r"""
     873        Ignore tag </pre> when inside highligh div.
     874
     875        EXAMPLES::
     876
     877            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     878            sage: p = SphinxHTMLProcessor()
     879            sage: p.all_pieces = 'a lot of stuff done '
     880            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     881            sage: p.keep_data = True
     882            sage: p.in_highlight_div = True
     883            sage: p.end_pre()
     884            sage: p.all_pieces
     885            'a lot of stuff done '
     886            sage: p.temp_pieces
     887            ['bunch ', 'of ', 'tmp ', 'strings']
     888
     889        ::
     890
     891            sage: p.all_pieces = 'a lot of stuff done '
     892            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     893            sage: p.keep_data = True
     894            sage: p.in_highlight_div = False
     895            sage: p.end_pre()
     896            sage: p.all_pieces
     897            'a lot of stuff done '
     898            sage: p.temp_pieces
     899            ['bunch ', 'of ', 'tmp ', 'strings', '</pre>']
     900        """
    297901        if self.in_highlight_div:
    298902            return
    299903        self.unknown_endtag('pre')
    300904
    301905    #Ignore forms
    302906    def start_form(self, attrs):
    303         #Hand of everything we've accumulated so far
     907        r"""
     908        Hand of everything we've accumulated so far.
     909
     910        Forms are ignored.
     911
     912        INPUT:
     913
     914        - ``attrs`` - list of tuple
     915
     916        EXAMPLES::
     917
     918            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     919            sage: p = SphinxHTMLProcessor()
     920            sage: p.all_pieces = 'a lot of stuff done '
     921            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     922            sage: attrs = []
     923            sage: p.start_form(attrs)
     924            sage: p.all_pieces
     925            'a lot of stuff done bunch of tmp strings'
     926            sage: p.temp_pieces
     927            []
     928        """
    304929        self.hand_off_temp_pieces('to_doc_pieces')
    305930        return
    306931
    307932    def end_form(self):
    308         #Ignore all of the pieces since we started
    309         #the form.
     933        r"""
     934        Ignore all of the pieces since we started
     935        the form.
     936
     937        EXAMPLES::
     938
     939            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     940            sage: p = SphinxHTMLProcessor()
     941            sage: p.all_pieces = 'a lot of stuff done '
     942            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     943            sage: p.end_form()
     944            sage: p.all_pieces
     945            'a lot of stuff done '
     946            sage: p.temp_pieces
     947            []
     948        """
    310949        self.hand_off_temp_pieces('ignore')
    311950        return
    312951
    313952    def start_span(self, attrs):
    314         #Ignore all spans that occur within highlighted blocks
     953        r"""
     954        Ignore all spans that occur within highlighted blocks
     955
     956        INPUT:
     957
     958        - ``attrs`` - list of tuple
     959
     960        EXAMPLES::
     961
     962            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     963            sage: p = SphinxHTMLProcessor()
     964            sage: p.all_pieces = 'a lot of stuff done '
     965            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     966            sage: p.keep_data = True
     967            sage: p.in_highlight_div = True
     968            sage: attrs = []
     969            sage: p.start_span(attrs)
     970            sage: p.all_pieces
     971            'a lot of stuff done '
     972            sage: p.temp_pieces
     973            ['bunch ', 'of ', 'tmp ', 'strings']
     974
     975        ::
     976
     977            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     978            sage: p = SphinxHTMLProcessor()
     979            sage: p.all_pieces = 'a lot of stuff done '
     980            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     981            sage: p.keep_data = True
     982            sage: p.in_highlight_div = False
     983            sage: attrs = []
     984            sage: p.start_span(attrs)
     985            sage: p.all_pieces
     986            'a lot of stuff done '
     987            sage: p.temp_pieces
     988            ['bunch ', 'of ', 'tmp ', 'strings', '<span>']
     989        """
    315990        if self.in_highlight_div:
    316991            return
    317992        self.unknown_starttag('span', attrs)
    318    
    319993    def end_span(self):
    320         #Ignore all spans that occur within highlighted blocks
     994        r"""
     995        Ignore all spans that occur within highlighted blocks
     996
     997        EXAMPLES::
     998
     999            sage: from sagenb.notebook.docHTMLProcessor import SphinxHTMLProcessor
     1000            sage: p = SphinxHTMLProcessor()
     1001            sage: p.all_pieces = 'a lot of stuff done '
     1002            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1003            sage: p.keep_data = True
     1004            sage: p.in_highlight_div = True
     1005            sage: p.end_span()
     1006            sage: p.all_pieces
     1007            'a lot of stuff done '
     1008            sage: p.temp_pieces
     1009            ['bunch ', 'of ', 'tmp ', 'strings']
     1010
     1011        ::
     1012
     1013            sage: p.all_pieces = 'a lot of stuff done '
     1014            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1015            sage: p.keep_data = True
     1016            sage: p.in_highlight_div = False
     1017            sage: p.end_span()
     1018            sage: p.all_pieces
     1019            'a lot of stuff done '
     1020            sage: p.temp_pieces
     1021            ['bunch ', 'of ', 'tmp ', 'strings', '</span>']
     1022        """
    3211023        if self.in_highlight_div:
    3221024            return       
    3231025        self.unknown_endtag('span')
     1026
     1027class docutilsHTMLProcessor(genericHTMLProcessor):
     1028    r"""
     1029    Translates output of the docutils parser rst2html into notebook text.
     1030
     1031    EXAMPLES::
     1032
     1033        sage: rst = ""
     1034        sage: rst += "Additions in Sage\n"
     1035        sage: rst += "-----------------\n"
     1036        sage: rst += "\n"
     1037        sage: rst += "Let's do easy computations with Sage::\n"
     1038        sage: rst += "\n"
     1039        sage: rst += "    s" + "age: 4 + 3\n"
     1040        sage: rst += "    7\n"
     1041        sage: rst += "    s" + "age: 1 - 2\n"
     1042        sage: rst += "    -1\n"
     1043        sage: rst += "\n"
     1044        sage: rst += "Let's do `x^2`::\n"
     1045        sage: rst += "\n"
     1046        sage: rst += "    s" + "age: x^2\n"
     1047        sage: rst += "    x^2\n"
     1048        sage: from docutils.core import publish_string
     1049        sage: html = publish_string(rst, writer_name='html')
     1050        sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1051        sage: p = docutilsHTMLProcessor()
     1052        sage: txt = p.process_doc_html(html)
     1053        sage: len(txt)
     1054        191
     1055        sage: print txt
     1056        <h1 class="title">Additions in Sage</h1>
     1057        <BLANKLINE>
     1058        <BLANKLINE>
     1059        <BLANKLINE>
     1060        <p>Let's do easy computations with Sage:</p>
     1061        <BLANKLINE>
     1062        {{{id=0|
     1063        4 + 3
     1064        ///
     1065        7
     1066        }}}
     1067        <BLANKLINE>
     1068        {{{id=1|
     1069        1 - 2
     1070        ///
     1071        -1
     1072        }}}
     1073        <BLANKLINE>
     1074        <p>Let's do $x^2$:</p>
     1075        <BLANKLINE>
     1076        {{{id=2|
     1077        x^2
     1078        ///
     1079        x^2
     1080        }}}
     1081        <BLANKLINE>
     1082        <BLANKLINE>
     1083
     1084    """
     1085    def reset(self):
     1086        """
     1087        Initialize necessary variables.  Called by
     1088        :meth:`SGMLParser.__init__`.
     1089
     1090        EXAMPLES::
     1091
     1092            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1093            sage: d = docutilsHTMLProcessor()    #indirect doctest
     1094            sage: d.keep_data
     1095            False
     1096            sage: d.in_pre_litteral_block
     1097            False
     1098            sage: d.in_div_footer_block
     1099            False
     1100            sage: d.temp_pieces
     1101            []
     1102            sage: d.all_pieces
     1103            ''
     1104            sage: d.cellcount
     1105            0
     1106        """
     1107        # flags
     1108        self.keep_data = False #don't keep anything before the <body> tag
     1109        self.in_pre_litteral_block = False
     1110        self.in_div_footer_block = False
     1111
     1112        # lists of what the parser keeps
     1113        self.temp_pieces = []
     1114        self.all_pieces = ''
     1115
     1116        # counters
     1117        self.cellcount = 0
     1118               
     1119        SGMLParser.reset(self)
     1120
     1121    def false_positive_input_output_cell(self, cell_piece):
     1122        r"""
     1123        Return the untouched html string of a false positive input output
     1124        cell.
     1125
     1126        A false positive input-output cell come from a block of code which
     1127        doesn't start with the sage prompt string 'sage:' or the Python
     1128        prompt '>>>'.
     1129
     1130        INPUT:
     1131
     1132        - ``cell_piece`` - string, a cell piece
     1133
     1134        OUPUT:
     1135
     1136            string
     1137
     1138        EXAMPLES::
     1139
     1140            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1141            sage: p = docutilsHTMLProcessor()
     1142            sage: s = "sage -rst2html -h"
     1143            sage: print p.false_positive_input_output_cell(s)
     1144            <pre class="literal-block">
     1145            sage -rst2html -h
     1146            </pre>
     1147
     1148        """
     1149        piece = '<pre class="literal-block">\n'
     1150        piece += cell_piece
     1151        piece = piece.replace('{','{&nbsp;')
     1152        piece = piece.replace('}','}&nbsp;')
     1153        piece += '\n</pre>'
     1154        return piece
     1155   
     1156    #############################################
     1157    ## Specific tag handlers
     1158    ##
     1159    # sage blocks
     1160    def start_pre(self, attrs):
     1161        r"""
     1162        INPUT:
     1163
     1164        - ``attrs`` - list of tuple
     1165
     1166        EXAMPLES::
     1167
     1168            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1169            sage: p = docutilsHTMLProcessor()
     1170            sage: p.all_pieces = 'a lot of stuff done '
     1171            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1172            sage: attrs = [('class', 'literal-block')]
     1173            sage: p.start_pre(attrs)
     1174            sage: p.all_pieces
     1175            'a lot of stuff done bunch of tmp strings'
     1176            sage: p.temp_pieces
     1177            []
     1178            sage: p.in_pre_litteral_block
     1179            True
     1180
     1181        ::
     1182
     1183            sage: p = docutilsHTMLProcessor()
     1184            sage: p.all_pieces = 'a lot of stuff done '
     1185            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1186            sage: p.keep_data = True
     1187            sage: attrs = [('class', 'something-else')]
     1188            sage: p.start_pre(attrs)
     1189            sage: p.all_pieces
     1190            'a lot of stuff done '
     1191            sage: p.temp_pieces
     1192            ['bunch ', 'of ', 'tmp ', 'strings', '<pre class="something-else">']
     1193            sage: p.in_pre_litteral_block
     1194            False
     1195        """
     1196        #Find out if we are starting a pre litteral-block
     1197        for name, value in attrs:
     1198            if name.lower()=='class' and value.lower()=='literal-block':
     1199                self.in_pre_litteral_block = True
     1200                self.hand_off_temp_pieces('to_doc_pieces')
     1201                return
     1202        self.unknown_starttag('pre',attrs)
     1203
     1204    def end_pre(self):
     1205        r"""
     1206        EXAMPLES::
     1207
     1208            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1209            sage: p = docutilsHTMLProcessor()
     1210            sage: p.all_pieces = 'a lot of stuff done '
     1211            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1212            sage: p.keep_data = True
     1213            sage: attrs = [('class', 'literal-block')]
     1214            sage: p.start_pre(attrs)
     1215            sage: sprompt = 'sa' + 'ge' + ': '    # to avoid problems with doctest script
     1216            sage: p.handle_data('%s4+4\n8\n%sx^2\nx^2\n' % (sprompt, sprompt))
     1217            sage: p.end_pre()
     1218            sage: print p.all_pieces
     1219            a lot of stuff done bunch of tmp strings
     1220            {{{id=0|
     1221            4+4
     1222            ///
     1223            8
     1224            }}}
     1225            <BLANKLINE>
     1226            {{{id=1|
     1227            x^2
     1228            ///
     1229            x^2
     1230            }}}
     1231            sage: p.temp_pieces
     1232            []
     1233            sage: p.in_pre_litteral_block
     1234            False
     1235
     1236        ::
     1237
     1238            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1239            sage: p = docutilsHTMLProcessor()
     1240            sage: p.all_pieces = 'a lot of stuff done '
     1241            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1242            sage: p.keep_data = True
     1243            sage: attrs = [('class', 'something-else')]
     1244            sage: p.start_pre(attrs)
     1245            sage: p.handle_data('some data')
     1246            sage: p.end_pre()
     1247            sage: print p.all_pieces
     1248            a lot of stuff done
     1249            sage: p.temp_pieces
     1250            ['bunch ', 'of ', 'tmp ', 'strings', '<pre class="something-else">', 'some data', '</pre>']
     1251            sage: p.in_pre_litteral_block
     1252            False
     1253        """
     1254        if self.in_pre_litteral_block:
     1255            self.in_pre_litteral_block = False
     1256            self.hand_off_temp_pieces('to_cell_pieces')
     1257            return
     1258        self.unknown_endtag('pre')
     1259
     1260    # Ignore div
     1261    def start_div(self, attrs):
     1262        r"""
     1263        INPUT:
     1264
     1265        - ``attrs`` - list of tuple
     1266
     1267        EXAMPLES::
     1268
     1269            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1270            sage: p = docutilsHTMLProcessor()
     1271            sage: p.all_pieces = 'a lot of stuff done '
     1272            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1273            sage: attrs = [('class', 'document'), ('id', 'title')]
     1274            sage: p.start_div(attrs)
     1275            sage: p.all_pieces
     1276            'a lot of stuff done '
     1277            sage: p.temp_pieces
     1278            ['bunch ', 'of ', 'tmp ', 'strings']
     1279        """
     1280        #Find out if we are starting a div footer block
     1281        for name, value in attrs:
     1282            if name.lower()=='class' and value.lower()=='footer':
     1283                self.hand_off_temp_pieces('to_doc_pieces')
     1284                self.keep_data = False
     1285                self.in_div_footer_block = True
     1286                return
     1287        return
     1288
     1289    def end_div(self):
     1290        r"""
     1291        EXAMPLES::
     1292
     1293            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1294            sage: p = docutilsHTMLProcessor()
     1295            sage: p.all_pieces = 'a lot of stuff done '
     1296            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1297            sage: p.end_div()
     1298            sage: p.all_pieces
     1299            'a lot of stuff done '
     1300            sage: p.temp_pieces
     1301            ['bunch ', 'of ', 'tmp ', 'strings']
     1302        """
     1303        if self.in_div_footer_block:
     1304            self.in_div_footer_block = False
     1305            self.keep_data = True
     1306        return
     1307
     1308    # latex role
     1309    def start_cite(self, attrs):
     1310        r"""
     1311        INPUT:
     1312
     1313        - ``attrs`` - list of tuple
     1314
     1315        EXAMPLES::
     1316
     1317            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1318            sage: p = docutilsHTMLProcessor()
     1319            sage: p.all_pieces = 'a lot of stuff done '
     1320            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1321            sage: p.keep_data = True
     1322            sage: attrs = []
     1323            sage: p.start_cite(attrs)
     1324            sage: p.all_pieces
     1325            'a lot of stuff done '
     1326            sage: p.temp_pieces
     1327            ['bunch ', 'of ', 'tmp ', 'strings', '$']
     1328        """
     1329        self.temp_pieces.append("$")
     1330        return
     1331
     1332    def end_cite(self):
     1333        r"""
     1334        EXAMPLES::
     1335
     1336            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1337            sage: p = docutilsHTMLProcessor()
     1338            sage: p.all_pieces = 'a lot of stuff done '
     1339            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1340            sage: p.keep_data = True
     1341            sage: p.start_cite([])
     1342            sage: p.handle_data('x^2')
     1343            sage: p.end_cite()
     1344            sage: p.all_pieces
     1345            'a lot of stuff done '
     1346            sage: p.temp_pieces
     1347            ['bunch ', 'of ', 'tmp ', 'strings', '$', 'x^2', '$']
     1348        """
     1349        self.temp_pieces.append("$")
     1350        return
     1351
     1352    # script (for example for mathjax)
     1353    def start_script(self, attrs):
     1354        r"""
     1355        INPUT:
     1356
     1357        - ``attrs`` - list of tuple
     1358
     1359        EXAMPLES::
     1360
     1361            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1362            sage: p = docutilsHTMLProcessor()
     1363            sage: p.all_pieces = 'a lot of stuff done '
     1364            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1365            sage: attrs = [('type', 'text/x-mathjax-config')]
     1366            sage: p.start_script(attrs)
     1367            sage: p.all_pieces
     1368            'a lot of stuff done '
     1369            sage: p.temp_pieces
     1370            ['bunch ', 'of ', 'tmp ', 'strings']
     1371            sage: p.keep_data
     1372            False
     1373        """
     1374        self.keep_data = False
     1375        return
     1376
     1377    def end_script(self):
     1378        r"""
     1379        EXAMPLES::
     1380
     1381            sage: from sagenb.notebook.docHTMLProcessor import docutilsHTMLProcessor
     1382            sage: p = docutilsHTMLProcessor()
     1383            sage: p.all_pieces = 'a lot of stuff done '
     1384            sage: p.temp_pieces = ['bunch ', 'of ', 'tmp ', 'strings']
     1385            sage: p.end_script()
     1386            sage: p.all_pieces
     1387            'a lot of stuff done '
     1388            sage: p.temp_pieces
     1389            ['bunch ', 'of ', 'tmp ', 'strings']
     1390            sage: p.keep_data
     1391            True
     1392        """
     1393        self.keep_data = True
     1394        return
     1395
  • sagenb/notebook/notebook.py

    diff --git a/sagenb/notebook/notebook.py b/sagenb/notebook/notebook.py
    a b class Notebook(object): 
    700700        elif ext.lower() == '.html':
    701701            # An html file, which should contain the static version of
    702702            # a sage help page, as generated by Sphinx
    703             W = self._import_worksheet_html(filename, owner)
     703            html = open(filename).read()
     704
     705            cell_pattern = r"""{{{id=.*?///.*?}}}"""
     706            docutils_pattern = r"""<meta name="generator" content="Docutils \S+: http://docutils\.sourceforge\.net/" />"""
     707            sphinx_pattern = r"""Created using <a href="http://sphinx\.pocoo\.org/">Sphinx</a>"""
     708
     709            if re.search(cell_pattern, html, re.DOTALL) is not None:
     710                W = self._import_worksheet_txt(filename, owner)
     711            elif re.search(docutils_pattern, html) is not None:
     712                W = self._import_worksheet_docutils_html(filename, owner)
     713            elif re.search(sphinx_pattern, html) is not None:
     714                W = self._import_worksheet_html(filename, owner)
     715            else:
     716                # Unrecognized html file
     717                # We do the default behavior, i.e. we import as if it was generated
     718                # by Sphinx web page
     719                W = self._import_worksheet_html(filename, owner)
     720        elif ext.lower() == '.rst':
     721            # A ReStructuredText file
     722            W = self._import_worksheet_rst(filename, owner)
    704723        else:
    705             # We only support txt, sws, and html files
     724            # We only support txt, sws, html and rst files
    706725            raise ValueError, "unknown extension '%s'"%ext
    707726        self.__worksheets[W.filename()] = W
    708727        return W
    class Notebook(object): 
    800819
    801820        INPUT:
    802821
    803         -  ``filename`` - a string; a filename that ends in .txt
     822        -  ``filename`` - a string; a filename that ends in .html
    804823
    805824        -  ``owner`` - a string; the imported worksheet's owner
    806825
    class Notebook(object): 
    853872            <p>Here are some computations:</p>
    854873            <BLANKLINE>
    855874            <div class="highlight-python">, Cell 0; in=1+1, out=
    856             2
    857             , TextCell 2: </div>
     875            2, TextCell 2: </div>
    858876            <BLANKLINE>
    859             </div></div></div></div]
     877            </div></div></div></div>]
    860878            sage: cell = W.cell_list()[1]
    861879            sage: cell.input_text()
    862880            u'1+1'
    class Notebook(object): 
    883901
    884902        return worksheet
    885903
     904    def _import_worksheet_rst(self, filename, owner):
     905        r"""
     906        Import a ReStructuredText file as a new worksheet.
     907
     908        INPUT:
     909
     910        -  ``filename`` - a string; a filename that ends in .rst
     911
     912        -  ``owner`` - a string; the imported worksheet's owner
     913
     914        OUTPUT:
     915
     916        -  a new instance of Worksheet
     917
     918        EXAMPLES:
     919
     920            sage: sprompt = 'sage' + ':'
     921            sage: rst = '\n'.join(['=============',
     922            ...       'Test Notebook',
     923            ...       '=============',
     924            ...       '',
     925            ...       'Let\'s do some computations::',
     926            ...       '',
     927            ...       '    %s 2+2' % sprompt,
     928            ...       '    4',
     929            ...       '',
     930            ...       '::',
     931            ...       '',
     932            ...       '    %s x^2' % sprompt,
     933            ...       '    x^2'])
     934            sage: name = tmp_filename() + '.rst'
     935            sage: fd = open(name,'w')
     936            sage: fd.write(rst)
     937            sage: fd.close()
     938            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb')
     939            sage: W = nb._import_worksheet_rst(name, 'admin')
     940            sage: W.name()
     941            u'Test Notebook'
     942            sage: W.owner()
     943            'admin'
     944            sage: W.cell_list()
     945            [TextCell 2: <h1 class="title">Test Notebook</h1>
     946            <BLANKLINE>
     947            <p>Let's do some computations:</p>, Cell 0; in=2+2, out=
     948            4, Cell 1; in=x^2, out=
     949            x^2]
     950            sage: cell = W.cell_list()[1]
     951            sage: cell.input_text()
     952            u'2+2'
     953            sage: cell.output_text()
     954            u'<pre class="shrunk">4</pre>'
     955
     956        """
     957        rst = open(filename).read()
     958
     959        # docutils removes the backslashes if they are not escaped This is
     960        # not practical because backslashes are almost never escaped in
     961        # Sage docstrings written in ReST.  So if the user wants the
     962        # backslashes to be escaped automatically, he adds the comment
     963        # ".. escape-backslashes" in the input file
     964        if re.search(r'^\.\.[ \t]+escape-backslashes', rst, re.MULTILINE) is not None:
     965            rst = rst.replace('\\','\\\\')
     966
     967        # Do the translation rst -> html (using docutils)
     968        from docutils.core import publish_parts
     969        D = publish_parts(rst, writer_name='html')
     970        title = D['title']
     971        html = D['whole']
     972
     973        # Do the translation html -> txt
     974        from docHTMLProcessor import docutilsHTMLProcessor
     975        translator = docutilsHTMLProcessor()
     976        worksheet_txt = translator.process_doc_html(html)
     977
     978        # Create worksheet
     979        worksheet = self.create_new_worksheet(title, owner)
     980        worksheet.edit_save(worksheet_txt)
     981
     982        return worksheet
     983
     984    def _import_worksheet_docutils_html(self, filename, owner):
     985        r"""
     986        Import a static html help page generated by docutils as a new
     987        worksheet.
     988
     989        INPUT:
     990
     991        -  ``filename`` - a string; a filename that ends in .html
     992
     993        -  ``owner`` - a string; the imported worksheet's owner
     994
     995        OUTPUT:
     996
     997        -  a new instance of Worksheet
     998
     999        EXAMPLES:
     1000
     1001            sage: sprompt = 'sage' + ':'
     1002            sage: rst = '\n'.join(['=============',
     1003            ...       'Test Notebook',
     1004            ...       '=============',
     1005            ...       '',
     1006            ...       'Let\'s do some computations::',
     1007            ...       '',
     1008            ...       '    %s 2+2' % sprompt,
     1009            ...       '    4',
     1010            ...       '',
     1011            ...       '::',
     1012            ...       '',
     1013            ...       '    %s x^2' % sprompt,
     1014            ...       '    x^2'])
     1015            sage: from docutils.core import publish_string
     1016            sage: html = publish_string(rst, writer_name='html')
     1017            sage: name = tmp_filename() + '.html'
     1018            sage: fd = open(name,'w')
     1019            sage: fd.write(html)
     1020            sage: fd.close()
     1021            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb')
     1022            sage: W = nb._import_worksheet_docutils_html(name, 'admin')
     1023            sage: W.name()
     1024            u'Test Notebook'
     1025            sage: W.owner()
     1026            'admin'
     1027            sage: W.cell_list()
     1028            [TextCell 2: <h1 class="title">Test Notebook</h1>
     1029            <BLANKLINE>
     1030            <p>Let's do some computations:</p>, Cell 0; in=2+2, out=
     1031            4, Cell 1; in=x^2, out=
     1032            x^2]
     1033            sage: cell = W.cell_list()[1]
     1034            sage: cell.input_text()
     1035            u'2+2'
     1036            sage: cell.output_text()
     1037            u'<pre class="shrunk">4</pre>'
     1038
     1039        """
     1040        html = open(filename).read()
     1041
     1042        # Do the translation html -> txt
     1043        from docHTMLProcessor import docutilsHTMLProcessor
     1044        translator = docutilsHTMLProcessor()
     1045        worksheet_txt = translator.process_doc_html(html)
     1046
     1047        # Extract title
     1048        from worksheet import extract_name
     1049        title, _ = extract_name(worksheet_txt)
     1050        if title.startswith('<h1 class="title">'):
     1051            title = title[18:]
     1052        if title.endswith('</h1>'):
     1053            title = title[:-5]
     1054
     1055        # Create worksheet
     1056        worksheet = self.create_new_worksheet(title, owner)
     1057        worksheet.edit_save(worksheet_txt)
     1058
     1059        return worksheet
     1060
    8861061    def change_worksheet_name_to_avoid_collision(self, worksheet):
    8871062        """
    8881063        Change the display name of the worksheet if there is already a