src/pyams_skin/metas.py
changeset 517 bc05061ceebb
parent 516 f4bd4666c8d2
child 520 f810009afcc6
equal deleted inserted replaced
516:f4bd4666c8d2 517:bc05061ceebb
    19 
    19 
    20 from pyams_i18n.interfaces import II18n
    20 from pyams_i18n.interfaces import II18n
    21 from pyams_skin.interfaces.configuration import IConfiguration
    21 from pyams_skin.interfaces.configuration import IConfiguration
    22 from pyams_skin.interfaces.extension import IGoogleAnalyticsInfo
    22 from pyams_skin.interfaces.extension import IGoogleAnalyticsInfo
    23 from pyams_skin.interfaces.metas import IHTMLContentMetas, IMetaHeader
    23 from pyams_skin.interfaces.metas import IHTMLContentMetas, IMetaHeader
       
    24 from pyams_skin.layer import IPyAMSUserLayer
    24 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
    25 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
    25 from pyams_utils.interfaces.site import ISiteRoot
    26 from pyams_utils.interfaces.site import ISiteRoot
    26 from pyams_utils.interfaces.tales import ITALESExtension
    27 from pyams_utils.interfaces.tales import ITALESExtension
       
    28 from pyams_utils.url import canonical_url
    27 
    29 
    28 
    30 
    29 #
    31 #
    30 # 'metas' TALES extension
    32 # 'metas' TALES extension
    31 #
    33 #
    52 def escape_value(value):
    54 def escape_value(value):
    53     return escape(value) if isinstance(value, str) else value
    55     return escape(value) if isinstance(value, str) else value
    54 
    56 
    55 
    57 
    56 @implementer(IMetaHeader)
    58 @implementer(IMetaHeader)
    57 class HTMLTagMeta(object):
    59 class BaseMeta(object):
       
    60     """Base HTML meta header"""
       
    61     
       
    62     def __init__(self, tag='meta', value=None, **attrs):
       
    63         self.tag = tag
       
    64         self.value = value
       
    65         self.attrs = attrs
       
    66         
       
    67     def render(self):
       
    68         attributes = ' '.join(('{}="{}"'.format(k, v) for k, v in self.attrs.items()))
       
    69         if self.value:
       
    70             return '<{0} {1}>{2}</{0}>'.format(self.tag, attributes, self.value)
       
    71         else:
       
    72             return '<{} {} />'.format(self.tag, attributes)
       
    73         
       
    74     
       
    75 class HTMLTagMeta(BaseMeta):
    58     """HTML tag meta header"""
    76     """HTML tag meta header"""
    59 
    77 
    60     def __init__(self, tag, content, **attrs):
    78     def __init__(self, tag, content, **attrs):
    61         self.tag = tag
    79         super(HTMLTagMeta, self).__init__(tag, content, **attrs)
    62         self.content = escape_value(content)
    80 
    63         self.attrs = attrs
    81 
    64 
    82 class HTTPEquivMeta(BaseMeta):
    65     def render(self):
       
    66         return '''<{tag} {attrs}>{content}</{tag}>'''.format(tag=self.tag,
       
    67                                                              attrs=' '.join(('{0}="{1}"'.format(*value) for value in
       
    68                                                                              self.attrs.items())),
       
    69                                                              content=self.content)
       
    70 
       
    71 
       
    72 @implementer(IMetaHeader)
       
    73 class HTTPEquivMeta(object):
       
    74     """HTTP-Equiv meta header"""
    83     """HTTP-Equiv meta header"""
    75 
    84 
    76     def __init__(self, http_equiv, value):
    85     def __init__(self, http_equiv, value):
    77         self.http_equiv = http_equiv
    86         super(HTTPEquivMeta, self).__init__(**{'http-equiv': http_equiv, 'content': escape_value(value)})
    78         self.value = escape_value(value)
    87 
    79 
    88 
    80     def render(self):
    89 class ValueMeta(BaseMeta):
    81         return '''<meta http-equiv="{http_equiv}" content="{value}" />'''.format(http_equiv=self.http_equiv,
       
    82                                                                                  value=self.value)
       
    83 
       
    84 
       
    85 @implementer(IMetaHeader)
       
    86 class ValueMeta(object):
       
    87     """Basic value meta header"""
    90     """Basic value meta header"""
    88 
    91 
    89     def __init__(self, name, value):
    92     def __init__(self, name, value):
    90         self.name = name
    93         super(ValueMeta, self).__init__(**{name: escape_value(value)})
    91         self.value = escape_value(value)
    94 
    92 
    95 
    93     def render(self):
    96 class ContentMeta(BaseMeta):
    94         return '''<meta {name}="{value}" />'''.format(name=self.name,
       
    95                                                       value=self.value)
       
    96 
       
    97 
       
    98 @implementer(IMetaHeader)
       
    99 class ContentMeta(object):
       
   100     """Content meta header"""
    97     """Content meta header"""
   101 
    98 
   102     def __init__(self, name, value):
    99     def __init__(self, name, value):
   103         self.name = name
   100         super(ContentMeta, self).__init__(name=name, content=escape_value(value))
   104         self.value = escape_value(value)
   101 
   105 
   102 
   106     def render(self):
   103 class PropertyMeta(BaseMeta):
   107         return '''<meta name="{name}" content="{value}" />'''.format(name=self.name,
       
   108                                                                      value=self.value)
       
   109 
       
   110 
       
   111 @implementer(IMetaHeader)
       
   112 class PropertyMeta(object):
       
   113     """Property meta header"""
   104     """Property meta header"""
   114 
   105 
   115     def __init__(self, property, value):
   106     def __init__(self, property, value):
   116         self.property = property
   107         super(PropertyMeta, self).__init__(property=property, content=escape_value(value))
   117         self.value = escape_value(value)
   108 
   118 
   109 
   119     def render(self):
   110 class SchemaMeta(BaseMeta):
   120         return '''<meta property="{property}" content="{value}" />'''.format(property=self.property,
       
   121                                                                              value=self.value)
       
   122 
       
   123 
       
   124 @implementer(IMetaHeader)
       
   125 class SchemaMeta(object):
       
   126     """Schema.org property meta header"""
   111     """Schema.org property meta header"""
   127 
   112 
   128     def __init__(self, name, value):
   113     def __init__(self, name, value):
   129         self.name = name
   114         super(SchemaMeta, self).__init__(itemprop=name, content=escape_value(value))
   130         self.value = escape_value(value)
   115 
   131 
   116 
   132     def render(self):
   117 class LinkMeta(BaseMeta):
   133         return '''<meta itemprop="{name}" content="{value}" />'''.format(name=self.name,
       
   134                                                                          value=self.value)
       
   135 
       
   136 
       
   137 @implementer(IMetaHeader)
       
   138 class LinkMeta(object):
       
   139     """Link meta header"""
   118     """Link meta header"""
   140 
   119 
   141     def __init__(self, rel, type, href, title=None):
   120     def __init__(self, rel, type, href, **kwargs):
   142         self.rel = rel
   121         super(LinkMeta, self).__init__('link', rel=rel, type=type, href=escape_value(href), **kwargs)
   143         self.type = type
       
   144         self.href = escape_value(href)
       
   145         self.title = title
       
   146 
       
   147     def render(self):
       
   148         title = ' title="{}"'.format(self.title) if self.title else ''
       
   149         return '''<link rel="{rel}" type="{type}" href="{href}" {title} />'''.format(rel=self.rel,
       
   150                                                                                      type=self.type,
       
   151                                                                                      href=self.href,
       
   152                                                                                      title=title)
       
   153 
   122 
   154 
   123 
   155 #
   124 #
   156 # Default metas headers
   125 # Default metas headers
   157 #
   126 #
   190         config = IConfiguration(self.context)
   159         config = IConfiguration(self.context)
   191         yield HTMLTagMeta('title', config.title)
   160         yield HTMLTagMeta('title', config.title)
   192         yield ContentMeta('description', config.description)
   161         yield ContentMeta('description', config.description)
   193 
   162 
   194 
   163 
       
   164 @adapter_config(name='canonical', context=(Interface, IPyAMSUserLayer, Interface), provides=IHTMLContentMetas)
       
   165 class CanonicalURLMetasAdapter(ContextRequestViewAdapter):
       
   166     """Canonical URL metas adapter"""
       
   167 
       
   168     order = 2
       
   169 
       
   170     def get_metas(self):
       
   171         target_url = canonical_url(self.context, self.request).replace('+', '%2B')
       
   172         yield BaseMeta(rel='canonical', href=target_url)
       
   173 
       
   174 
   195 @adapter_config(name='content-type', context=(Interface, Interface, Interface), provides=IHTMLContentMetas)
   175 @adapter_config(name='content-type', context=(Interface, Interface, Interface), provides=IHTMLContentMetas)
   196 class ContentTypeMetasAdapter(ContextRequestViewAdapter):
   176 class ContentTypeMetasAdapter(ContextRequestViewAdapter):
   197     """Content-type metas adapter"""
   177     """Content-type metas adapter"""
   198 
   178 
   199     order = 10
   179     order = 10
   202     def get_metas():
   182     def get_metas():
   203         yield HTTPEquivMeta('Content-Type', 'text/html; charset=utf-8')
   183         yield HTTPEquivMeta('Content-Type', 'text/html; charset=utf-8')
   204         yield ValueMeta('charset', 'utf-8')
   184         yield ValueMeta('charset', 'utf-8')
   205 
   185 
   206 
   186 
   207 @adapter_config(name='analytics', context=(Interface, Interface, Interface), provides=IHTMLContentMetas)
   187 @adapter_config(name='google-site-verification', context=(Interface, Interface, Interface), provides=IHTMLContentMetas)
   208 class VerificationCodeMetasAdapter(ContextRequestViewAdapter):
   188 class VerificationCodeMetasAdapter(ContextRequestViewAdapter):
   209     """Google verification code metas adapter"""
   189     """Google verification code metas adapter"""
   210 
   190 
   211     order = 20
   191     order = 11
   212 
   192 
   213     def __new__(cls, context, request, view):
   193     def __new__(cls, context, request, view):
   214         info = IGoogleAnalyticsInfo(request.root)
   194         info = IGoogleAnalyticsInfo(request.root)
   215         if not info.verification_code:
   195         if not info.verification_code:
   216             return None
   196             return None