From a206c9132fab50bec9c70ea450bdb71cbc576648 Mon Sep 17 00:00:00 2001 From: Kernc Date: Mon, 23 Feb 2015 04:43:58 +0100 Subject: [PATCH] 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 --- pelican/readers.py | 19 ++++++++++--------- pelican/utils.py | 9 ++++++++- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index 3656cd96..8f57cf88 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -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): diff --git a/pelican/utils.py b/pelican/utils.py index caac8e61..13880753 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -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):