Annotation of kupuMPIWG/plone/html2captioned.py, revision 1.1

1.1     ! dwinter     1: # Portal transform for images with captions
        !             2: #
        !             3: # We want to be able to support captions in images.
        !             4: # The easiest way to do this is to define a Portal Transform which is
        !             5: # applied to the HTML body text on output.
        !             6: #
        !             7: # The transform finds all the embedded images, and replaces them with
        !             8: # an appropriate chunk of HTML to include the caption.
        !             9: #
        !            10: from Products.CMFCore.utils import getToolByName
        !            11: from Products.PortalTransforms.interfaces import itransform
        !            12: from DocumentTemplate.DT_Util import html_quote
        !            13: from DocumentTemplate.DT_Var import newline_to_br
        !            14: import re
        !            15: 
        !            16: __revision__ = '$Id$'
        !            17: 
        !            18: # IMAGE_PATTERN matches an image tag on its own, or an image tag
        !            19: # enclosed in a simple <p> or <div>. In the latter case we strip out
        !            20: # the enclosing tag since we are going to insert our own.
        !            21: PATIMG = '\\<img[^>]+class=[^=>]*captioned[^>]+\\>'
        !            22: PATA = '(?:\\<a[^>]*\\>'+PATIMG+'\\</a\\>)' + '|' + PATIMG
        !            23: PAT0 = '('+PATA+')'
        !            24: PAT1 = '<(?:p|div)[^>]*>'+PAT0 + '</(?:p|div)>' + '|' + PAT0
        !            25: IMAGE_PATTERN = re.compile(PAT1, re.IGNORECASE)
        !            26: 
        !            27: # Regex to match stupid IE attributes. In IE generated HTML an
        !            28: # attribute may not be enclosed by quotes if it doesn't contain
        !            29: # certain punctuation.
        !            30: ATTR_VALUE = '=(?:"?)(?P<%s>(?<=")[^"]*|[^ \/>]*)'
        !            31: ATTR_CLASS = ATTR_VALUE % 'class'
        !            32: ATTR_WIDTH = ATTR_VALUE % 'width'
        !            33: 
        !            34: ATTR_PATTERN = re.compile('''
        !            35:     (?P<tag>\<
        !            36:      ( class%s
        !            37:      | src="resolveuid/(?P<src>([^/"#? ]*))
        !            38:      | width%s
        !            39:      | .
        !            40:      )*\>
        !            41:     )''' % (ATTR_CLASS, ATTR_WIDTH), re.VERBOSE)
        !            42: 
        !            43: CLASS_PATTERN = re.compile('\s*class=("[^"]*captioned[^"]*"|[^" \/>]+)')
        !            44: IMAGE_TEMPLATE = '''\
        !            45: <div class="%(class)s" style="width:%(width)spx;">
        !            46:  <div style="width:%(width)spx;">
        !            47:   %(tag)s
        !            48:  </div>
        !            49:  <div class="image-caption">
        !            50:   %(caption)s
        !            51:  </div>
        !            52: </div>
        !            53: '''
        !            54: 
        !            55: UID_PATTERN = re.compile('(?P<tag><(?:a|img) [^>]*(?:src|href)=")(?P<url>[^"]*resolveuid/(?P<uid>[^"#? ]*))')
        !            56: 
        !            57: class HTMLToCaptioned:
        !            58:     """Transform which adds captions to images embedded in HTML"""
        !            59:     __implements__ = itransform
        !            60:     __name__ = "html_to_captioned"
        !            61:     inputs = ('text/html',)
        !            62:     output = "text/x-html-captioned"
        !            63:     
        !            64:     def __init__(self, name=None):
        !            65:         self.config_metadata = {
        !            66:             'inputs' : ('list', 'Inputs', 'Input(s) MIME type. Change with care.'),
        !            67:             }
        !            68:         if name:
        !            69:             self.__name__ = name
        !            70: 
        !            71:     def name(self):
        !            72:         return self.__name__
        !            73: 
        !            74:     def __getattr__(self, attr):
        !            75:         if attr == 'inputs':
        !            76:             return self.config['inputs']
        !            77:         if attr == 'output':
        !            78:             return self.config['output']
        !            79:         raise AttributeError(attr)
        !            80: 
        !            81:     def convert(self, data, idata, filename=None, **kwargs):
        !            82:         """convert the data, store the result in idata and return that
        !            83:         optional argument filename may give the original file name of received data
        !            84:         additional arguments given to engine's convert, convertTo or __call__ are
        !            85:         passed back to the transform
        !            86:         
        !            87:         The object on which the translation was invoked is available as context
        !            88:         (default: None)
        !            89:         """
        !            90:         context = kwargs.get('context', None)
        !            91:         if context:
        !            92:             at_tool = context.archetype_tool
        !            93: 
        !            94:         if context and at_tool:        
        !            95:             def replaceImage(match):
        !            96:                 tag = match.group(1) or match.group(2)
        !            97:                 attrs = ATTR_PATTERN.match(tag)
        !            98:                 src = attrs.group('src')
        !            99:                 klass = attrs.group('class')
        !           100:                 width = attrs.group('width')
        !           101:                 if src:
        !           102:                     d = attrs.groupdict()
        !           103:                     target = at_tool.reference_catalog.lookupObject(src)
        !           104:                     if target:
        !           105:                         d['caption'] = newline_to_br(target.Description())
        !           106:                         d['tag'] = CLASS_PATTERN.sub('', d['tag'])
        !           107:                         if not width:
        !           108:                             d['width'] = target.getWidth()
        !           109: 
        !           110:                         return IMAGE_TEMPLATE % d
        !           111:                 return match.group(0) # No change
        !           112: 
        !           113:             html = IMAGE_PATTERN.sub(replaceImage, data)
        !           114: 
        !           115:             # Replace urls that use UIDs with human friendly urls.
        !           116:             def replaceUids(match):
        !           117:                 tag = match.group('tag')
        !           118:                 uid = match.group('uid')
        !           119:                 target = at_tool.reference_catalog.lookupObject(uid)
        !           120:                 if target:
        !           121:                     return tag + target.absolute_url()
        !           122:                 return match.group(0)
        !           123: 
        !           124:             html = UID_PATTERN.sub(replaceUids, html)
        !           125:             
        !           126:             idata.setData(html)
        !           127:             return idata
        !           128: 
        !           129:         # No context to use for replacements, so don't bother trying.
        !           130:         return data
        !           131: 
        !           132: def register():
        !           133:     return HTMLToCaptioned()
        !           134: 
        !           135: def initialize():
        !           136:     engine = getToolByName(portal, 'portal_transforms')
        !           137:     engine.registerTransform(register())

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>