Repository: getpelican/pelican

Issue:
HTML reader uses incorrect "contents" attribute for meta tag, should be "content"
The HTML reader tries to extract values from a meta tag using the "contents" attribute. However, meta tags have no "contents" attribute (see http://www.w3.org/TR/html401/struct/global.html#h-7.4.4.2), it should be "content". 



Discussion:
Hi Kyle. Thanks for the issue report. Might you be willing to implement a fix for this?


Resolving patch:
diff --git a/pelican/readers.py b/pelican/readers.py
--- a/pelican/readers.py
+++ b/pelican/readers.py
@@ -5,6 +5,7 @@
 import logging
 import os
 import re
+import logging
 try:
     import docutils
     import docutils.core
@@ -47,6 +48,8 @@
     'author': Author,
 }
 
+logger = logging.getLogger(__name__)
+
 
 class Reader(object):
     enabled = True
@@ -199,7 +202,7 @@ class HTMLReader(Reader):
     enabled = True
 
     class _HTMLParser(HTMLParser):
-        def __init__(self, settings):
+        def __init__(self, settings, filename):
             HTMLParser.__init__(self)
             self.body = ''
             self.metadata = {}
@@ -207,6 +210,8 @@ def __init__(self, settings):
 
             self._data_buffer = ''
 
+            self._filename = filename
+
             self._in_top_level = True
             self._in_head = False
             self._in_title = False
@@ -275,7 +280,11 @@ def build_tag(self, tag, attrs, close_tag):
 
         def _handle_meta_tag(self, attrs):
             name = self._attr_value(attrs, 'name').lower()
-            contents = self._attr_value(attrs, 'contents', '')
+            contents = self._attr_value(attrs, 'content', '')
+            if not contents:
+                contents = self._attr_value(attrs, 'contents', '')
+                if contents:
+                    logger.warning("Meta tag attribute 'contents' used in file %s, should be changed to 'content'", self._filename)
 
             if name == 'keywords':
                 name = 'tags'
@@ -288,7 +297,7 @@ def _attr_value(cls, attrs, name, default=None):
     def read(self, filename):
         """Parse content and metadata of HTML files"""
         with pelican_open(filename) as content:
-            parser = self._HTMLParser(self.settings)
+            parser = self._HTMLParser(self.settings, filename)
             parser.feed(content)
             parser.close()
 


Test patch:
diff --git a/pelican/tests/content/article_with_keywords.html b/pelican/tests/content/article_with_keywords.html
--- a/pelican/tests/content/article_with_keywords.html
+++ b/pelican/tests/content/article_with_keywords.html
@@ -1,6 +1,6 @@
 <html>
     <head>
         <title>This is a super article !</title>
-        <meta name="keywords" contents="foo, bar, foobar" />
+        <meta name="keywords" content="foo, bar, foobar" />
     </head>
 </html>
diff --git a/pelican/tests/content/article_with_metadata.html b/pelican/tests/content/article_with_metadata.html
--- a/pelican/tests/content/article_with_metadata.html
+++ b/pelican/tests/content/article_with_metadata.html
@@ -1,12 +1,12 @@
 <html>
     <head>
         <title>This is a super article !</title>
-        <meta name="tags" contents="foo, bar, foobar" />
-        <meta name="date" contents="2010-12-02 10:14" />
-        <meta name="category" contents="yeah" />
-        <meta name="author" contents="Alexis Métaireau" />
-        <meta name="summary" contents="Summary and stuff" />
-        <meta name="custom_field" contents="http://notmyidea.org" />
+        <meta name="tags" content="foo, bar, foobar" />
+        <meta name="date" content="2010-12-02 10:14" />
+        <meta name="category" content="yeah" />
+        <meta name="author" content="Alexis Métaireau" />
+        <meta name="summary" content="Summary and stuff" />
+        <meta name="custom_field" content="http://notmyidea.org" />
     </head>
     <body>
         Multi-line metadata should be supported
diff --git a/pelican/tests/content/article_with_metadata_and_contents.html b/pelican/tests/content/article_with_metadata_and_contents.html
new file mode 100644
--- /dev/null
+++ b/pelican/tests/content/article_with_metadata_and_contents.html
@@ -0,0 +1,15 @@
+<html>
+    <head>
+        <title>This is a super article !</title>
+        <meta name="tags" contents="foo, bar, foobar" />
+        <meta name="date" contents="2010-12-02 10:14" />
+        <meta name="category" contents="yeah" />
+        <meta name="author" contents="Alexis Métaireau" />
+        <meta name="summary" contents="Summary and stuff" />
+        <meta name="custom_field" contents="http://notmyidea.org" />
+    </head>
+    <body>
+        Multi-line metadata should be supported
+        as well as <strong>inline markup</strong>.
+    </body>
+</html>
diff --git a/pelican/tests/content/article_with_uppercase_metadata.html b/pelican/tests/content/article_with_uppercase_metadata.html
--- a/pelican/tests/content/article_with_uppercase_metadata.html
+++ b/pelican/tests/content/article_with_uppercase_metadata.html
@@ -1,6 +1,6 @@
 <html>
     <head>
         <title>This is a super article !</title>
-        <meta name="Category" contents="Yeah" />
+        <meta name="Category" content="Yeah" />
     </head>
 </html>
diff --git a/pelican/tests/test_readers.py b/pelican/tests/test_readers.py
--- a/pelican/tests/test_readers.py
+++ b/pelican/tests/test_readers.py
@@ -350,6 +350,21 @@ def test_article_with_metadata(self):
         for key, value in expected.items():
             self.assertEqual(value, page.metadata[key], key)
 
+    def test_article_with_metadata_and_contents_attrib(self):
+        page = self.read_file(path='article_with_metadata_and_contents.html')
+        expected = {
+            'category': 'yeah',
+            'author': 'Alexis Métaireau',
+            'title': 'This is a super article !',
+            'summary': 'Summary and stuff',
+            'date': datetime.datetime(2010, 12, 2, 10, 14),
+            'tags': ['foo', 'bar', 'foobar'],
+            'custom_field': 'http://notmyidea.org',
+        }
+        for key, value in expected.items():
+            self.assertEqual(value, page.metadata[key], key)
+
+
     def test_article_with_null_attributes(self):
         page = self.read_file(path='article_with_null_attributes.html')