|
1 # |
|
2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net> |
|
3 # All Rights Reserved. |
|
4 # |
|
5 # This software is subject to the provisions of the Zope Public License, |
|
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. |
|
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED |
|
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
|
10 # FOR A PARTICULAR PURPOSE. |
|
11 # |
|
12 |
|
13 __docformat__ = 'restructuredtext' |
|
14 |
|
15 |
|
16 # import standard library |
|
17 |
|
18 # import interfaces |
|
19 from pyams_skin.interfaces.extension import IGoogleAnalyticsInfo |
|
20 from pyams_skin.interfaces.metas import IHTMLContentMetas, IMetaHeader |
|
21 from pyams_utils.interfaces.tales import ITALESExtension |
|
22 from pyramid.interfaces import IRequest |
|
23 |
|
24 # import packages |
|
25 from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter |
|
26 from zope.interface import implementer, Interface |
|
27 |
|
28 |
|
29 # |
|
30 # 'metas' TALES extension |
|
31 # |
|
32 |
|
33 @adapter_config(name='metas', context=(Interface, IRequest, Interface), provides=ITALESExtension) |
|
34 class MetasTalesExtension(ContextRequestViewAdapter): |
|
35 """extension:metas TALES extension""" |
|
36 |
|
37 def render(self, context=None): |
|
38 if context is None: |
|
39 context = self.context |
|
40 result = [] |
|
41 for name, adapter in sorted(self.request.registry.getAdapters((context, self.request, self.view), |
|
42 IHTMLContentMetas), |
|
43 key=lambda x: getattr(x[1], 'order', 9999)): |
|
44 result.extend([meta.render() for meta in adapter.get_metas()]) |
|
45 return '\n\t'.join(result) |
|
46 |
|
47 |
|
48 # |
|
49 # Custom metas headers |
|
50 # |
|
51 |
|
52 @implementer(IMetaHeader) |
|
53 class HTTPEquivMeta(object): |
|
54 """HTTP-Equiv meta header""" |
|
55 |
|
56 def __init__(self, http_equiv, value): |
|
57 self.http_equiv = http_equiv |
|
58 self.value = value |
|
59 |
|
60 def render(self): |
|
61 return '''<meta http-equiv="{http_equiv}" content="{value}" />'''.format(http_equiv=self.http_equiv, |
|
62 value=self.value) |
|
63 |
|
64 |
|
65 @implementer(IMetaHeader) |
|
66 class ValueMeta(object): |
|
67 """Basic value meta header""" |
|
68 |
|
69 def __init__(self, name, value): |
|
70 self.name = name |
|
71 self.value = value |
|
72 |
|
73 def render(self): |
|
74 return '''<meta {name}="{value}" />'''.format(name=self.name, |
|
75 value=self.value) |
|
76 |
|
77 |
|
78 @implementer(IMetaHeader) |
|
79 class ContentMeta(object): |
|
80 """Content meta header""" |
|
81 |
|
82 def __init__(self, name, value): |
|
83 self.name = name |
|
84 self.value = value |
|
85 |
|
86 def render(self): |
|
87 return '''<meta name="{name}" content="{value}" />'''.format(name=self.name, |
|
88 value=self.value) |
|
89 |
|
90 |
|
91 @implementer(IMetaHeader) |
|
92 class PropertyMeta(object): |
|
93 """Property meta header""" |
|
94 |
|
95 def __init__(self, property, value): |
|
96 self.property = property |
|
97 self.value = value |
|
98 |
|
99 def render(self): |
|
100 return '''<meta property="{property}" content="{value}" />'''.format(property=self.property, |
|
101 value=self.value) |
|
102 |
|
103 |
|
104 @implementer(IMetaHeader) |
|
105 class LinkMeta(object): |
|
106 """Link meta header""" |
|
107 |
|
108 def __init__(self, rel, type, href): |
|
109 self.rel = rel |
|
110 self.type = type |
|
111 self.href = href |
|
112 |
|
113 def render(self): |
|
114 return '''<link rel="{rel}" type="{type}" href="{href}" />'''.format(rel=self.rel, |
|
115 type=self.type, |
|
116 href=self.href) |
|
117 |
|
118 |
|
119 # |
|
120 # Default metas headers |
|
121 # |
|
122 |
|
123 @adapter_config(name='layout', context=(Interface, Interface, Interface), provides=IHTMLContentMetas) |
|
124 class LayoutMetasAdapter(ContextRequestViewAdapter): |
|
125 """Basic layout metas adapter""" |
|
126 |
|
127 order = -1 |
|
128 |
|
129 @staticmethod |
|
130 def get_metas(): |
|
131 yield HTTPEquivMeta('X-UA-Compatible', 'IE=edge,chrome=1') |
|
132 yield ContentMeta('HandheldFriendly', 'True') |
|
133 yield ContentMeta('viewport', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no') |
|
134 |
|
135 |
|
136 @adapter_config(name='content-type', context=(Interface, Interface, Interface), provides=IHTMLContentMetas) |
|
137 class ContentTypeMetasAdapter(ContextRequestViewAdapter): |
|
138 """Content-type metas adapter""" |
|
139 |
|
140 order = 10 |
|
141 |
|
142 @staticmethod |
|
143 def get_metas(): |
|
144 yield HTTPEquivMeta('Content-Type', 'text/html; charset=utf-8') |
|
145 yield ValueMeta('charset', 'utf-8') |
|
146 |
|
147 |
|
148 @adapter_config(name='analytics', context=(Interface, Interface, Interface), provides=IHTMLContentMetas) |
|
149 class VerificationCodeMetasAdapter(ContextRequestViewAdapter): |
|
150 """Google verification code metas adapter""" |
|
151 |
|
152 order = 20 |
|
153 |
|
154 def __new__(cls, context, request, view): |
|
155 info = IGoogleAnalyticsInfo(request.root) |
|
156 if not info.verification_code: |
|
157 return None |
|
158 return ContextRequestViewAdapter.__new__(cls) |
|
159 |
|
160 def get_metas(self): |
|
161 info = IGoogleAnalyticsInfo(self.request.root) |
|
162 yield ContentMeta('google-site-verification', info.verification_code) |