Add support for YAML metadata in Markdown files

~~Python-Markdown>=2.6 and its meta extension supports YAML headers
and optional `yaml` switch which, when used, parses data with
PyYAML and hence a wee bit different metadata object gets provided.~~
Not anymore.

YAML is supported by python-markdown-yaml-meta-data extension
which uses PyYAML, which returns parsed lists of strings instead
of raw strings, datetime objects instead of string date
representations etc. Pelican needed only slight adjusting, and
now support Jekyll-like YAML headers with aforementioned Markdown
extension.

Related:
* https://github.com/teoric/python-markdown-yaml-meta-data
* https://github.com/getpelican/pelican-plugins/pull/382
* https://github.com/waylan/Python-Markdown/issues/390#issuecomment-76200467
This commit is contained in:
Kernc 2015-02-23 04:43:58 +01:00
commit a206c9132f
2 changed files with 18 additions and 10 deletions

View file

@ -30,7 +30,9 @@ from pelican.utils import get_date, pelican_open, FileStampDataCacher, SafeDatet
def strip_split(text, sep=','):
"""Return a list of stripped, non-empty substrings, delimited by sep."""
items = [x.strip() for x in text.split(sep)]
if not isinstance(text, list):
text = text.split(sep)
items = [x.strip() for x in text]
return [x for x in items if x]
@ -90,6 +92,8 @@ class BaseReader(object):
def process_metadata(self, name, value):
if name in METADATA_PROCESSORS:
if isinstance(value, list) and len(value) == 1:
value = value[0]
return METADATA_PROCESSORS[name](value, self.settings)
return value
@ -249,16 +253,13 @@ class MarkdownReader(BaseReader):
summary = self._md.convert(summary_values)
output[name] = self.process_metadata(name, summary)
elif name in METADATA_PROCESSORS:
if len(value) > 1:
logger.warning('Duplicate definition of `%s` '
'for %s. Using first one.', name, self._source_path)
output[name] = self.process_metadata(name, value[0])
elif len(value) > 1:
# handle list metadata as list of string
output[name] = self.process_metadata(name, value)
else:
# otherwise, handle metadata as single string
elif isinstance(value, list) and len(value) == 1:
# handle metadata as a single string
output[name] = self.process_metadata(name, value[0])
else:
# otherwise, handle metadata as single item
output[name] = self.process_metadata(name, value)
return output
def read(self, source_path):

View file

@ -222,9 +222,16 @@ def get_date(string):
If no format matches the given date, raise a ValueError.
"""
string = re.sub(' +', ' ', string)
default = SafeDatetime.now().replace(hour=0, minute=0,
second=0, microsecond=0)
if isinstance(string, datetime.datetime):
# Return datetime object as SafeDatetime
return default.replace(year=string.year, month=string.month,
day=string.day, hour=string.hour,
minute=string.minute, second=string.second,
microsecond=string.microsecond,
tzinfo=string.tzinfo)
string = re.sub('[ _]+', ' ', string)
try:
return dateutil.parser.parse(string, default=default)
except (TypeError, ValueError):