Changeset 113

Show
Ignore:
Timestamp:
04/07/07 15:14:04 (2 years ago)
Author:
rgrp
Message:

Minorish changes to annotations stuff which mean Annotation is now working (finally!). This is a result of:

  1. Fix to annotater in previous commit
  2. Introduction of necessary marginalia metadata section in the pages.
  3. Fix to have (roughly) correct url in annotationInit stuff.

Still various issues:

  • marginalia js breaks down for large texts when adding annotation anywhere away from top of page (i.e. all texts except phoenix and turtle).
  • not setting marginalia text url correctly so annotation not specific to a given text (so annotations show up on all texts ...)

* /trunk/src/shakespeare/format.py

/trunk/src/shakespeare/format_test.py:

  • Add metadata section (just using default values and not yet configured from wsgiplain).
  • Use page_url (though default to http://localhost:8080)
  • Use id item correctly.

* /trunk/src/shakespeare/template/view_annotate.html

Add show annotations and hid annotations button.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/shakespeare/format.py

    Revision 99 Revision 113
    1""" 1""" 
    2Format texts in a variety of ways 2Format texts in a variety of ways 
    3""" 3""" 
    4 4 
    5def format_text(fileobj, format): 5def format_text(fileobj, format): 
    6    """Format a provided text in a variety of ways. 6    """Format a provided text in a variety of ways. 
    7 7 
    8    @format: the name specifying the format to use 8    @format: the name specifying the format to use 
    9    """ 9    """ 
    10    formatter = None 10    formatter = None 
    11    if format == 'plain': 11    if format == 'plain': 
    12        formatter = TextFormatterPlain(fileobj) 12        formatter = TextFormatterPlain(fileobj) 
    13    elif format == 'lineno': 13    elif format == 'lineno': 
    14        formatter = TextFormatterLineno(fileobj) 14        formatter = TextFormatterLineno(fileobj) 
    15    elif format == 'annotate': 15    elif format == 'annotate': 
    16        formatter = TextFormatterAnnotate(fileobj) 16        formatter = TextFormatterAnnotate(fileobj) 
    17    else: 17    else: 
    18        raise ValueError('Unknown format: %s' % format) 18        raise ValueError('Unknown format: %s' % format) 
    19    return formatter.format() 19    return formatter.format() 
    20 20 
    21 21 
    22class TextFormatter(object): 22class TextFormatter(object): 
    23    """Abstract base class for formatters. 23    """Abstract base class for formatters. 
    24    """ 24    """ 
    25 25 
    26    def __init__(self, file=None): 26    def __init__(self, file=None): 
    27        """ 27        """ 
    28        @file: file-like object containing a text in plain txt with utf-8 28        @file: file-like object containing a text in plain txt with utf-8 
    29        encoding 29        encoding 
    30        """ 30        """ 
    31        self.file = file 31        self.file = file 
    32 32 
    33    def format(self): 33    def format(self): 
    34        """Format the supplied text. 34        """Format the supplied text. 
    35 35 
    36        The returned string will be in unicode format with utf-8 encoding 36        The returned string will be in unicode format with utf-8 encoding 
    37        """ 37        """ 
    38        raise NotImplementedError() 38        raise NotImplementedError() 
    39 39 
    40    def escape_chars(self, text): 40    def escape_chars(self, text): 
    41        return text.replace('&', '&amp;').replace('<', '&lt;') 41        return text.replace('&', '&amp;').replace('<', '&lt;') 
    42 42 
    43class TextFormatterPlain(TextFormatter): 43class TextFormatterPlain(TextFormatter): 
    44    """Format the text as plain text (in an html <pre> tag). 44    """Format the text as plain text (in an html <pre> tag). 
    45    """ 45    """ 
    46 46 
    47    def format(self): 47    def format(self): 
    48        out = unicode(self.file.read(), 'utf-8') 48        out = unicode(self.file.read(), 'utf-8') 
    49        out = self.escape_chars(out) 49        out = self.escape_chars(out) 
    50        out = \ 50        out = \ 
    51u''' 51u''' 
    52<pre> 52<pre> 
    53    %s 53    %s 
    54</pre>''' % out 54</pre>''' % out 
    55        return out 55        return out 
    56 56 
    57class TextFormatterLineno(TextFormatter): 57class TextFormatterLineno(TextFormatter): 
    58    """Format the text to have line numbers. 58    """Format the text to have line numbers. 
    59    """ 59    """ 
    60 60 
    61    def format(self): 61    def format(self): 
    62        result = '' 62        result = '' 
    63        count = 0 63        count = 0 
    64        for line in self.file.readlines(): 64        for line in self.file.readlines(): 
    65            tlineno = unicode(count).ljust(4) # assume line no < 10000 65            tlineno = unicode(count).ljust(4) # assume line no < 10000 
    66            tline = unicode(line, 'utf-8').rstrip()  66            tline = unicode(line, 'utf-8').rstrip()  
    67            tline = self.escape_chars(tline) 67            tline = self.escape_chars(tline) 
    68            result += u'<pre id="%s">%s %s</pre>\n' % (count, tlineno, tline) 68            result += u'<pre id="%s">%s %s</pre>\n' % (count, tlineno, tline) 
    69            count += 1 69            count += 1 
    70        return result 70        return result 
    71 71 
    72 72 
    73class TextFormatterAnnotate(TextFormatter): 73class TextFormatterAnnotate(TextFormatter): 
    74    """Format the text in a manner suitable for marginalia annotation. 74    """Format the text in a manner suitable for marginalia annotation. 
    75    """ 75    """ 
    76    entry_template = u''' 76    entry_template = u''' 
    77    <div id="%(id)s" class="hentry"> 77    <div id="%(id)s" class="hentry"> 
    78        <h3 class="entry-title">%(title)s</h3> 78        <h3 class="entry-title">%(title)s</h3> 
    79        <div class="entry-content"> 79        <div class="entry-content"> 
    80            %(content)s 80            %(content)s 
    81        </div><!-- /entry-content --> 81        </div><!-- /entry-content --> 
      82        <p class="metadata"> 
      83            <a rel="bookmark" href="%(page_url)s#%(id)s">#</a> 
      84            <span class="author">%(author)s</span> 
      85        </p> 
    82        <div class="notes"> 86        <div class="notes"> 
    83            <button class="createAnnotation" onclick="createAnnotation('m1',true)" title="Click here to create an annotation">&gt;</button> 87            <button class="createAnnotation" onclick="createAnnotation('%(id)s',true)" title="Click here to create an annotation">&gt;</button> 
    84            <ol> 88            <ol> 
    85                <li></li> 89                <li></li> 
    86            </ol> 90            </ol> 
    87        </div><!-- /notes --> 91        </div><!-- /notes --> 
    88    </div><!-- /hentry --> 92    </div><!-- /hentry --> 
    89''' 93''' 
    90 94 
    91    def format(self): 95    def format(self): 
    92        line_numberer = TextFormatterLineno(self.file) 96        line_numberer = TextFormatterLineno(self.file) 
    93        text_with_linenos = line_numberer.format() 97        text_with_linenos = line_numberer.format() 
    94        # todo chunking 98        # todo chunking 
    95        values = { 99        values = { 
    96                'content' : text_with_linenos, 100                'content' : text_with_linenos, 
    97                'title' : 'Test Stuff', 101                'title' : 'Test Stuff', 
    98                'id' : 'm2', 102                'id' : 'm2', 
      103                'page_url' : 'http://localhost:8080/', 
      104                'author' : 'Nemo', 
    99                } 105                } 
    100        result = self.entry_template % values 106        result = self.entry_template % values 
    101        return result 107        return result 
    102 108 
  • trunk/src/shakespeare/format_test.py

    Revision 99 Revision 113
    1import StringIO 1import StringIO 
    2import shakespeare.format 2import shakespeare.format 
    3 3 
    4 4 
    5starttext = unicode('''Blah \xc3\xa6 5starttext = unicode('''Blah \xc3\xa6 
    6blah & blah''', 'utf-8') 6blah & blah''', 'utf-8') 
    7 7 
    8sometext = starttext.replace('&', '&amp;') 8sometext = starttext.replace('&', '&amp;') 
    9 9 
    10class TestTextFormatter: 10class TestTextFormatter: 
    11    formatter = shakespeare.format.TextFormatter() 11    formatter = shakespeare.format.TextFormatter() 
    12 12 
    13    def test_escape_chars(self): 13    def test_escape_chars(self): 
    14        out = self.formatter.escape_chars(starttext) 14        out = self.formatter.escape_chars(starttext) 
    15        assert out == sometext 15        assert out == sometext 
    16 16 
    17 17 
    18class TestTextFormatterPlain: 18class TestTextFormatterPlain: 
    19    fileobj = StringIO.StringIO(starttext.encode('utf-8')) 19    fileobj = StringIO.StringIO(starttext.encode('utf-8')) 
    20    formatter = shakespeare.format.TextFormatterPlain(fileobj) 20    formatter = shakespeare.format.TextFormatterPlain(fileobj) 
    21    exp = u''' 21    exp = u''' 
    22<pre> 22<pre> 
    23    %s 23    %s 
    24</pre>''' % sometext 24</pre>''' % sometext 
    25 25 
    26    def test_format(self): 26    def test_format(self): 
    27        out = self.formatter.format() 27        out = self.formatter.format() 
    28        assert out == self.exp 28        assert out == self.exp 
    29 29 
    30 30 
    31class TestTextFormatterLineno: 31class TestTextFormatterLineno: 
    32    fileobj = StringIO.StringIO(starttext.encode('utf-8')) 32    fileobj = StringIO.StringIO(starttext.encode('utf-8')) 
    33    formatter = shakespeare.format.TextFormatterLineno(fileobj) 33    formatter = shakespeare.format.TextFormatterLineno(fileobj) 
    34    exp = u'''<pre id="0">0    Blah \xe6</pre> 34    exp = u'''<pre id="0">0    Blah \xe6</pre> 
    35<pre id="1">1    blah &amp; blah</pre> 35<pre id="1">1    blah &amp; blah</pre> 
    36''' 36''' 
    37 37 
    38    def test_format(self): 38    def test_format(self): 
    39        out = self.formatter.format() 39        out = self.formatter.format() 
    40        assert out == self.exp 40        assert out == self.exp 
    41 41 
    42def test_text_format():   
    43    formatlist = [ ('plain', TestTextFormatterPlain),   
    44        ('lineno', TestTextFormatterLineno),   
    45        ('annotate', TestTextFormatterAnnotate),   
    46        ]   
    47    for item in formatlist:   
    48        fileobj = StringIO.StringIO(starttext.encode('utf-8'))   
    49        tout = shakespeare.format.format_text(fileobj, item[0])   
    50        assert tout == item[1].exp   
    51 42 
    52class TestTextFormatterAnnotate: 43class TestTextFormatterAnnotate: 
    53 44 
    54    fileobj = StringIO.StringIO(starttext.encode('utf-8')) 45    fileobj = StringIO.StringIO(starttext.encode('utf-8')) 
    55    formatter = shakespeare.format.TextFormatterAnnotate(fileobj) 46    formatter = shakespeare.format.TextFormatterAnnotate(fileobj) 
    56    exp = u''' 47    exp = u''' 
    57    <div id="m2" class="hentry"> 48    <div id="m2" class="hentry"> 
    58        <h3 class="entry-title">Test Stuff</h3> 49        <h3 class="entry-title">Test Stuff</h3> 
    59        <div class="entry-content"> 50        <div class="entry-content"> 
    60            <pre id="0">0    Blah \xe6</pre> 51            <pre id="0">0    Blah \xe6</pre> 
    61<pre id="1">1    blah &amp; blah</pre> 52<pre id="1">1    blah &amp; blah</pre> 
    62 53 
    63        </div><!-- /entry-content --> 54        </div><!-- /entry-content --> 
      55        <p class="metadata"> 
      56            <a rel="bookmark" href="http://localhost:8080/#m2">#</a> 
      57            <span class="author">Nemo</span> 
      58        </p> 
    64        <div class="notes"> 59        <div class="notes"> 
    65            <button class="createAnnotation" onclick="createAnnotation('m1',true)" title="Click here to create an annotation">&gt;</button> 60            <button class="createAnnotation" onclick="createAnnotation('m2',true)" title="Click here to create an annotation">&gt;</button> 
    66            <ol> 61            <ol> 
    67                <li></li> 62                <li></li> 
    68            </ol> 63            </ol> 
    69        </div><!-- /notes --> 64        </div><!-- /notes --> 
    70    </div><!-- /hentry --> 65    </div><!-- /hentry --> 
    71''' 66''' 
    72     67     
    73    def test_format(self): 68    def test_format(self): 
    74        out = self.formatter.format() 69        out = self.formatter.format() 
    75        print '"%s"' % out.encode('utf-8') 70        print '"%s"' % out.encode('utf-8') 
    76        print '"%s"' % self.exp.encode('utf-8') 71        print '"%s"' % self.exp.encode('utf-8') 
    77        assert out == self.exp 72        assert out == self.exp 
    78 73 
    79    def test_valid_xml(self): 74    def test_valid_xml(self): 
    80        import genshi 75        import genshi 
    81        outxml = genshi.XML(self.exp) 76        outxml = genshi.XML(self.exp) 
    82 77 
      78 
      79def test_text_format(): 
      80    formatlist = [ ('plain', TestTextFormatterPlain), 
      81        ('lineno', TestTextFormatterLineno), 
      82        ('annotate', TestTextFormatterAnnotate), 
      83        ] 
      84    for item in formatlist: 
      85        fileobj = StringIO.StringIO(starttext.encode('utf-8')) 
      86        tout = shakespeare.format.format_text(fileobj, item[0]) 
      87        assert tout == item[1].exp 
      88 
  • trunk/src/shakespeare/template/view_annotate.html

    Revision 99 Revision 113
    1<html xmlns:py="http://genshi.edgewall.org/" 1<html xmlns:py="http://genshi.edgewall.org/" 
    2  xmlns:xi="http://www.w3.org/2001/XInclude"> 2  xmlns:xi="http://www.w3.org/2001/XInclude"> 
    3 3 
    4  <py:def function="page_title">View Works - Annotate</py:def> 4  <py:def function="page_title">View Works - Annotate</py:def> 
    5  <head> 5  <head> 
    6  <py:def function="page_specific_css"> 6  <py:def function="page_specific_css"> 
    7    ${marginalia_media} 7    ${marginalia_media} 
    8    <style type="text/css" py:def="page_specific_css"> 8    <style type="text/css" py:def="page_specific_css"> 
    9      body 9      body 
    10      { 10      { 
    11        margin: 0; 11        margin: 0; 
    12        padding: 0; 12        padding: 0; 
    13      } 13      } 
    14 14 
    15      div.frame 15      div.frame 
    16      { 16      { 
    17        height: 90%; 17        height: 90%; 
    18        overflow: auto; 18        overflow: auto; 
    19        float: left; 19        float: left; 
    20        padding: 1em; 20        padding: 1em; 
    21      } 21      } 
    22 22 
    23      div.singleview 23      div.singleview 
    24      { 24      { 
    25        padding: 2em; 25        padding: 2em; 
    26        padding-left: 10%; 26        padding-left: 10%; 
    27        padding-right: 10%; 27        padding-right: 10%; 
    28      } 28      } 
    29 29 
    30      /* ensure we take up the whole width */ 30      /* ensure we take up the whole width */ 
    31      div.multiview 31      div.multiview 
    32      { 32      { 
    33        width: 100%; 33        width: 100%; 
    34        height: 90%; 34        height: 90%; 
    35      } 35      } 
    36    </style> 36    </style> 
    37  </py:def> 37  </py:def> 
    38  </head> 38  </head> 
    39 39 
    40  <div py:match="content"> 40  <div py:match="content"> 
      41    <div id="annotation-controls"> 
      42      <form> 
      43        <input type="button" onclick='showAllAnnotations( "http://localhost:8080/#*")' value="Show Annotations" /><br /> 
      44        <input type="button" onclick='hideAllAnnotations( "http://localhost:8080/#*")' value="Hide Annotations" /><br /> 
      45      </form> 
      46    </div> 
    41    <div py:if="len(texts) == 1" class="singleview"> 47    <div py:if="len(texts) == 1" class="singleview"> 
    42                        ${texts[0]} 48                        ${texts[0]} 
    43    </div> 49    </div> 
    44    <div class="multiview" py:if="len(texts) > 1" > 50    <div class="multiview" py:if="len(texts) > 1" > 
    45      <div py:for="text in texts" class="frame" 51      <div py:for="text in texts" class="frame" 
    46        style="width: ${frame_width}%;" > 52        style="width: ${frame_width}%;" > 
    47        ${text} 53        ${text} 
    48      </div> 54      </div> 
    49    </div> 55    </div> 
    50  </div> 56  </div> 
    51 57 
    52  <xi:include href="layout.html" /> 58  <xi:include href="layout.html" /> 
    53</html> 59</html>