diff --git a/README.md b/README.md index 683f4cd..587ee38 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ point you can forward the document on to your lightweight markup processor of choice. You might even want to use some the meta-data to configure the behavior of your lightweight markup processor. -YAML Meta-Data (not yet implemented) +YAML Meta-Data -------------- Given a document that contains YAML style meta-data, simply pass it to @@ -32,9 +32,13 @@ doc, data = get_data(doc) The `docdata.yamldata.get_data` function will return a tuple which contains the document with the meta-data removed and the meta-data as returned by the YAML -parser. As YAML provides for and recognizes various types out-of-the-box, -no additional features need to be provided. The document can now be passed to -your lightweight markup processor of choice. +parser. Note that if the YAML root data structure parsed by YAML is not a +dictionary, it is assumed that no data is defined, the YAML block is not +removed from the document, and an empty dict is returned as data. + +As YAML provides for and recognizes various types out-of-the-box, no additional +features need to be provided. The document can now be passed to your lightweight +markup processor of choice. MultiMarkdown Meta-Data ----------------------- diff --git a/docdata/yamldata.py b/docdata/yamldata.py index 5b6b38a..70e62ca 100644 --- a/docdata/yamldata.py +++ b/docdata/yamldata.py @@ -6,7 +6,15 @@ """ +import re import yaml +try: + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeLoader + + +BLOCK_RE = re.compile(r'^-{3}[ \t]*\n(.*?\n)(?:\.{3}|-{3})[ \t]*\n', re.UNICODE|re.DOTALL) def get_data(doc): @@ -15,4 +23,15 @@ def get_data(doc): Returns a tuple of document and data. """ - pass # TODO: implement this \ No newline at end of file + data = {} + m = BLOCK_RE.match(doc) + if m: + try: + data = yaml.load(m.group(1), SafeLoader) + if isinstance(data, dict): + doc = doc[m.end():].lstrip('\n') + else: + data = {} + except: + pass + return doc, data \ No newline at end of file diff --git a/tests/test_yamldata.py b/tests/test_yamldata.py index e69de29..873867f 100644 --- a/tests/test_yamldata.py +++ b/tests/test_yamldata.py @@ -0,0 +1,90 @@ +import unittest +import datetime +from docdata import yamldata + +class TestYamlData(unittest.TestCase): + def test_yaml_data(self): + doc = '''--- +Author: John Doe +Date: 2015-05-08 14:15:16 +Integer: 0x2A +--- + +Document content. +''' + self.assertEqual( + yamldata.get_data(doc), + ( + 'Document content.\n', + { + 'Author': 'John Doe', + 'Date': datetime.datetime(2015, 5, 8, 14, 15, 16), + 'Integer': 42 + } + ) + ) + + def test_end_deliminator(self): + doc = '''--- +Author: John Doe +Date: 2015-05-08 +Integer: 42 +... +Document content. +''' + self.assertEqual( + yamldata.get_data(doc), + ( + 'Document content.\n', + { + 'Author': 'John Doe', + 'Date': datetime.date(2015, 5, 8), + 'Integer': 42 + } + ) + ) + + def test_bad_deliminator(self): + doc = '''--- +Author: John Doe +Date: 2015-05-08 +Integer: 42 +-.- +Document content. +''' + self.assertEqual( + yamldata.get_data(doc), + (doc, {}) + ) + + def test_blank_first_line(self): + doc = ''' +--- +Author: John Doe +Date: 2015-05-08 +Integer: 42 +--- +Document content. +''' + self.assertEqual( + yamldata.get_data(doc), + (doc, {}) + ) + + def test_bad_yaml(self): + doc = '''--- +foo +... +Document content. +''' + self.assertEqual( + yamldata.get_data(doc), + (doc, {}) + ) + + def test_no_yaml(self): + doc = 'Document content.' + self.assertEqual( + yamldata.get_data(doc), + (doc, {}) + ) \ No newline at end of file