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 |