--- a/reportlab/platypus/paragraph.py Fri Jan 26 12:46:22 2007 +0000
+++ b/reportlab/platypus/paragraph.py Mon Jan 29 13:02:38 2007 +0000
@@ -109,10 +109,15 @@
nSpaces = 0
for f in words:
if hasattr(f,'cbDefn'):
- func = getattr(tx._canvas,f.cbDefn.name,None)
- if not func:
- raise AttributeError, "Missing %s callback attribute '%s'" % (f.cbDefn.kind,f.cbDefn.name)
- func(tx._canvas,f.cbDefn.kind,f.cbDefn.label)
+ name = f.cbDefn.name
+ kind = f.cbDefn.kind
+ if kind=='anchor':
+ tx._canvas.bookmarkHorizontal(name,cur_x,tx._y+tx._leading)
+ else:
+ func = getattr(tx._canvas,name,None)
+ if not func:
+ raise AttributeError, "Missing %s callback attribute '%s'" % (kind,name)
+ func(tx._canvas,kind,f.cbDefn.label)
if f is words[-1]: tx._textOut('',1)
else:
cur_x_s = cur_x + nSpaces*ws
@@ -410,6 +415,9 @@
if kind=='GoToR': link = parts[1]
tx._canvas.linkURL(link, rect, relative=1, kind=kind)
else:
+ if link[0]=='#':
+ link = link[1:]
+ scheme=''
tx._canvas.linkRect("", scheme!='document' and link or parts[1], rect, relative=1)
def _do_link_line(i, t_off, ws, tx):
--- a/reportlab/platypus/paraparser.py Fri Jan 26 12:46:22 2007 +0000
+++ b/reportlab/platypus/paraparser.py Mon Jan 29 13:02:38 2007 +0000
@@ -120,6 +120,15 @@
'target': ('link', None),
'href': ('link', None),
}
+_anchorAttrMap = {'fontSize': ('fontSize', _num),
+ 'fontName': ('fontName', None),
+ 'name': ('name', None),
+ 'fg': ('textColor', toColor),
+ 'color':('textColor', toColor),
+ 'backcolor':('backColor',toColor),
+ 'bgcolor':('backColor',toColor),
+ 'href': ('href', None),
+ }
def _addAttributeNames(m):
K = m.keys()
@@ -326,7 +335,14 @@
# fg/textColor/color=color
# backcolor/backColor/bgcolor=color
# dest/destination/target/href/link=target
-# <a> alias for link
+# <a>anchor text</link>
+# attributes of anchors
+# fontSize=num
+# fontName=name
+# fg/textColor/color=color
+# backcolor/backColor/bgcolor=color
+# href=href
+# <a name="anchorpoint"/>
# <unichar name="unicode character name"/>
# <unichar value="unicode code point"/>
# <greek> - </greek>
@@ -407,8 +423,34 @@
del self._stack[-1]
assert frag.link!=None
- start_a = start_link
- end_a = end_link
+ #### anchor
+ def start_a(self, attributes):
+ A = self.getAttributes(attributes,_anchorAttrMap)
+ if A.get('name',None):
+ if len(A)>1:
+ self._syntax_error('<a name="..."/> anchor variant only allows name attribute')
+ A = dict(name=A['name'])
+ A['_selfClosingTag'] = 'anchor'
+ elif not A.get('href',None):
+ self._syntax_error('<a> tag must have name or href attribute')
+ else:
+ A['link'] = A.pop('href') #convert to our link form
+ self._push(**A)
+
+ def end_a(self):
+ frag = self._stack[-1]
+ sct = getattr(frag,'_selfClosingTag','')
+ if sct:
+ assert sct=='anchor' and frag.name,'Parser failure in <a/>'
+ defn = frag.cbDefn = ABag()
+ defn.label = defn.kind = 'anchor'
+ defn.name = frag.name
+ del frag.name, frag._selfClosingTag
+ self.handle_data('')
+ self._pop()
+ else:
+ del self._stack[-1]
+ assert frag.link!=None
#### super script
def start_super( self, attributes ):
--- a/reportlab/test/test_platypus_paragraphs.py Fri Jan 26 12:46:22 2007 +0000
+++ b/reportlab/test/test_platypus_paragraphs.py Mon Jan 29 13:02:38 2007 +0000
@@ -10,7 +10,7 @@
from types import StringType, ListType
from reportlab.test import unittest
-from reportlab.test.utils import makeSuiteForClasses, outputfile, printLocation, outputfile
+from reportlab.test.utils import makeSuiteForClasses, outputfile, printLocation
from reportlab.pdfbase.pdfmetrics import stringWidth
from reportlab.platypus.paraparser import ParaParser
@@ -250,6 +250,8 @@
phonemic and morphological analysis.''']
story =[]
a = story.append
+ a(Paragraph("This should %lt;a href=\"#theEnd\" color=\"blue\"><a href=\"#theEnd\" color=\"blue\">jump</a></a> jump to the end!",style=normal))
+ a(Paragraph("This should %lt;a href=\"#thePenultimate\" color=\"blue\"><a href=\"#thePenultimate\" color=\"blue\">jump</a></a> jump to the penultimate page!",style=normal))
for mode in (0,1):
text0 = texts[0]
text1 = texts[1]
@@ -259,11 +261,14 @@
for t in ('u','strike'):
for n in xrange(6):
for s in (normal,normal_center,normal_right,normal_just,normal_indent, normal_indent_lv_2):
+ if n==4 and s==normal_center and t=='strike':
+ a(Paragraph("The second jump at the beginning should come here <a name=\"thePenultimate\"/><a name=\"thePenultimate\"/>!",style=normal))
a(Paragraph('n=%d style=%s tag=%s'%(n,s.name,t),style=normal_sp))
a(Paragraph('%s<%s>%s</%s>. %s <%s>%s</%s>. %s' % (
(s==normal_indent_lv_2 and '<seq id="document" inc="no"/>.<seq id="document_lv_2"/>' or ''),
t,' '.join((n+1)*['A']),t,text0,t,' '.join((n+1)*['A']),t,text1),
style=s))
+ a(Paragraph("The jump at the beginning should come here <a name=\"theEnd\"/><a name=\"theEnd\"/>!",style=normal))
doc = MyDocTemplate(outputfile('test_platypus_paragraphs_ul.pdf'))
doc.build(story)