From 1b4cc1e595a67db8c88bf1c47f8ecb915d1aab67 Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Sun, 30 Nov 2014 19:34:08 -0500 Subject: Updated author email --- .gitignore | 1 + setup.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 3f7b30a..a542fb3 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ MANIFEST .tox/* .coverage htmlcov/* +*komodo* \ No newline at end of file diff --git a/setup.py b/setup.py index 7e8862c..923334d 100755 --- a/setup.py +++ b/setup.py @@ -235,9 +235,9 @@ setup( description='Python implementation of Markdown.', long_description=long_description, author='Manfred Stienstra, Yuri takhteyev and Waylan limberg', - author_email='markdown [at] freewisdom.org', + author_email='waylan.limberg [at] icloud.com', maintainer='Waylan Limberg', - maintainer_email='waylan [at] gmail.com', + maintainer_email='waylan.limberg [at] icloud.com', license='BSD License', packages=['markdown', 'markdown.extensions'], scripts=['bin/%s' % SCRIPT_NAME], -- cgit v1.2.3 From 1339e8b87f926745b781139df7a23798ce922197 Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Sun, 30 Nov 2014 22:12:14 -0500 Subject: Upped version to 2.6.dev We are ready to start adding/changing features now. --- markdown/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown/__version__.py b/markdown/__version__.py index 33d0ac5..911e340 100644 --- a/markdown/__version__.py +++ b/markdown/__version__.py @@ -5,7 +5,7 @@ # (major, minor, micro, alpha/beta/rc/final, #) # (1, 1, 2, 'alpha', 0) => "1.1.2.dev" # (1, 2, 0, 'beta', 2) => "1.2b2" -version_info = (2, 5, 2, 'final', 0) +version_info = (2, 6, 0, 'alpha', 0) def _get_version(): -- cgit v1.2.3 From ef6eb032b2e08f866b900cbc4d130b18200f712e Mon Sep 17 00:00:00 2001 From: Kernc Date: Tue, 25 Nov 2014 00:13:39 +0100 Subject: Add YAML support to Meta extension By default, this only supports YAML deliminators (`---`) and adds no additional behavior. In other words, parsing is unchanged. However, with the `yaml` option set, PyYAML will parse the metadata. Thanks to @kernc for suggesting the idea and doing the work on this. --- docs/extensions/meta_data.txt | 32 +++++++++++++++++++++++------ markdown/extensions/meta.py | 48 ++++++++++++++++++++++++++++++++++++------- tests/test_extensions.py | 42 +++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 13 deletions(-) diff --git a/docs/extensions/meta_data.txt b/docs/extensions/meta_data.txt index 406755b..517d3e6 100644 --- a/docs/extensions/meta_data.txt +++ b/docs/extensions/meta_data.txt @@ -44,9 +44,16 @@ If a line is indented by 4 or more spaces, that line is assumed to be an additional line of the value for the previous keyword. A keyword may have as many lines as desired. -The first blank line ends all meta-data for the document. Therefore, the first -line of a document must not be blank. All meta-data is stripped from the -document prior to any further processing by Markdown. +The first blank line ends all meta-data for the document. Therefore, the first +line of a document must not be blank. + +Alternatively, if the first line in the document is `---`, a YAML document +separator, then the meta-data is searched for between it and the next `---` +(or `...`) line. Even though YAML delimitors are supported, meta-data is +not parsed as YAML unless the `yaml` option is set (see below). + +All meta-data is stripped from the document prior to any further processing +by Markdown. Usage ----- @@ -54,7 +61,15 @@ Usage See [Extensions](index.html) for general extension usage, specify `markdown.extensions.meta` as the name of the extension. -This extension does not accept any special configuration options. +The following options are provided to configure the output: + +* **`yaml`**: Support meta-data specified in YAML format. + + Default: `False` + + If `yaml` is set to `True`, the lines between `---` separators are parsed + as a full YAML object. PyYAML is required for this, and a warning is + issued if PyYAML (or equivalent) isn't available. Accessing the Meta-Data ----------------------- @@ -85,8 +100,13 @@ line breaks if desired. Or the items could be joined where appropriate. No assumptions are made regarding the data. It is simply passed as found to the `Meta` attribute. -Perhaps the meta-data could be passed into a template system, or used by -various Markdown extensions. The possibilities are left to the imagination of +Note, if `yaml` option is set, the resulting `Meta` attribute is the object as +returned by `yaml.load()` and may deviate significantly from the above +description (e.g. may be a list of dicts, with value objects other than +strings, ...). + +Perhaps the meta-data could be passed into a template system, or used by +various Markdown extensions. The possibilities are left to the imagination of the developer. Compatible Extensions diff --git a/markdown/extensions/meta.py b/markdown/extensions/meta.py index a733a8a..cf8074f 100644 --- a/markdown/extensions/meta.py +++ b/markdown/extensions/meta.py @@ -20,36 +20,68 @@ from __future__ import unicode_literals from . import Extension from ..preprocessors import Preprocessor import re +import logging + +try: # pragma: no cover + import yaml + try: + from yaml import CSafeLoader as SafeLoader + except ImportError: + from yaml import SafeLoader +except ImportError: + yaml = None + +log = logging.getLogger('MARKDOWN') # Global Vars META_RE = re.compile(r'^[ ]{0,3}(?P[A-Za-z0-9_-]+):\s*(?P.*)') META_MORE_RE = re.compile(r'^[ ]{4,}(?P.*)') +YAML_BEGIN_RE = re.compile(r'^-{3}(\s.*)?') +YAML_END_RE = re.compile(r'^(-{3}|\.{3})(\s.*)?') class MetaExtension (Extension): """ Meta-Data extension for Python-Markdown. """ + def __init__(self, *args, **kwargs): + self.config = { + 'yaml': [False, "Parse meta data specified as a " + "'---' delimited YAML front matter"], + } + super(MetaExtension, self).__init__(*args, **kwargs) def extendMarkdown(self, md, md_globals): """ Add MetaPreprocessor to Markdown instance. """ - - md.preprocessors.add( - "meta", MetaPreprocessor(md), ">normalize_whitespace" - ) + md.preprocessors.add("meta", + MetaPreprocessor(md, self.getConfigs()), + ">normalize_whitespace") class MetaPreprocessor(Preprocessor): """ Get Meta-Data. """ + def __init__(self, md, config): + self.config = config + super(MetaPreprocessor, self).__init__(md) + def run(self, lines): """ Parse Meta-Data and store in Markdown.Meta. """ meta = {} key = None + yaml_block = [] + have_yaml = False + if lines and YAML_BEGIN_RE.match(lines[0]): + have_yaml = True + lines.pop(0) + if self.config['yaml'] and not yaml: # pragma: no cover + log.warning('Document with YAML header, but PyYAML unavailable') while lines: line = lines.pop(0) - if line.strip() == '': - break # blank line - done m1 = META_RE.match(line) - if m1: + if line.strip() == '' or have_yaml and YAML_END_RE.match(line): + break # blank line or end of YAML header - done + elif have_yaml and self.config['yaml'] and yaml: + yaml_block.append(line) + elif m1: key = m1.group('key').lower().strip() value = m1.group('value').strip() try: @@ -64,6 +96,8 @@ class MetaPreprocessor(Preprocessor): else: lines.insert(0, line) break # no meta data - done + if yaml_block: + meta = yaml.load('\n'.join(yaml_block), SafeLoader) self.markdown.Meta = meta return lines diff --git a/tests/test_extensions.py b/tests/test_extensions.py index a037915..e24118f 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -8,6 +8,7 @@ continue to work as advertised. This used to be accomplished by doctests. """ from __future__ import unicode_literals +import datetime import unittest import markdown @@ -513,6 +514,28 @@ The body. This is paragraph one.''' } ) + def testYamlMetaData(self): + """ Test metadata specified as simple YAML. """ + + text = '''--- +Title: A Test Doc. +Author: [Waylan Limberg, John Doe] +Blank_Data: +--- + +The body. This is paragraph one.''' + self.assertEqual( + self.md.convert(text), + '

The body. This is paragraph one.

' + ) + self.assertEqual( + self.md.Meta, { + 'author': ['[Waylan Limberg, John Doe]'], + 'blank_data': [''], + 'title': ['A Test Doc.'] + } + ) + def testMissingMetaData(self): """ Test document without Meta Data. """ @@ -530,6 +553,25 @@ The body. This is paragraph one.''' self.assertEqual(self.md.convert(text), '') self.assertEqual(self.md.Meta, {'title': ['No newline']}) + def testYamlObjectMetaData(self): + """ Test metadata specified as a complex YAML object. """ + md = markdown.Markdown(extensions=[markdown.extensions.meta.MetaExtension(yaml=True)]) + text = '''--- +Author: John Doe +Date: 2014-11-29 14:15:16 +Integer: 0x16 +--- + +Some content.''' + self.assertEqual(md.convert(text), '

Some content.

') + self.assertEqual( + md.Meta, { + 'Author': 'John Doe', + 'Date': datetime.datetime(2014, 11, 29, 14, 15, 16), + 'Integer': 22 + } + ) + class TestWikiLinks(unittest.TestCase): """ Test Wikilinks Extension. """ -- cgit v1.2.3