Add asciidoc reader support

http://www.methods.co.nz/asciidoc/index.html

Processes files ending in .asc with asciidoc. Extra arguments can be
passed by using the ASCIIDOC_OPTIONS config setting
This commit is contained in:
Brian C. Lane 2012-10-28 07:37:53 -07:00
commit 49f481e399
9 changed files with 114 additions and 6 deletions

View file

@ -24,6 +24,7 @@ Release history
* Add the gzip_cache plugin which compresses common text files into a ``.gz`` * Add the gzip_cache plugin which compresses common text files into a ``.gz``
file within the same directory as the original file to prevent the server file within the same directory as the original file to prevent the server
(e.g. Nginx) from compressing files during an HTTP call. (e.g. Nginx) from compressing files during an HTTP call.
* Add AsciiDoc support
3.0 (2012-08-08) 3.0 (2012-08-08)
================== ==================

View file

@ -42,6 +42,10 @@ Markdown library as well::
$ pip install Markdown $ pip install Markdown
If you want to use AsciiDoc you need to install it from `source
<http://www.methods.co.nz/asciidoc/INSTALL.html>`_ or use your operating
system's package manager.
Upgrading Upgrading
--------- ---------

View file

@ -4,7 +4,7 @@ Pelican
Pelican is a static site generator, written in Python_. Pelican is a static site generator, written in Python_.
* Write your weblog entries directly with your editor of choice (vim!) * Write your weblog entries directly with your editor of choice (vim!)
in reStructuredText_ or Markdown_ in reStructuredText_, Markdown_ or AsciiDoc_
* Includes a simple CLI tool to (re)generate the weblog * Includes a simple CLI tool to (re)generate the weblog
* Easy to interface with DVCSes and web hooks * Easy to interface with DVCSes and web hooks
* Completely static output is easy to host anywhere * Completely static output is easy to host anywhere
@ -74,6 +74,7 @@ A French version of the documentation is available at :doc:`fr/index`.
.. _Python: http://www.python.org/ .. _Python: http://www.python.org/
.. _reStructuredText: http://docutils.sourceforge.net/rst.html .. _reStructuredText: http://docutils.sourceforge.net/rst.html
.. _Markdown: http://daringfireball.net/projects/markdown/ .. _Markdown: http://daringfireball.net/projects/markdown/
.. _AsciiDoc: http://www.methods.co.nz/asciidoc/index.html
.. _Jinja2: http://jinja.pocoo.org/ .. _Jinja2: http://jinja.pocoo.org/
.. _`Pelican documentation`: http://docs.getpelican.com/latest/ .. _`Pelican documentation`: http://docs.getpelican.com/latest/
.. _`Pelican's internals`: http://docs.getpelican.com/en/latest/internals.html .. _`Pelican's internals`: http://docs.getpelican.com/en/latest/internals.html

View file

@ -12,8 +12,8 @@ original author wrote with some software design information.
Overall structure Overall structure
================= =================
What Pelican does is take a list of files and process them into some What Pelican does is take a list of files and process them into some sort of
sort of output. Usually, the input files are reStructuredText and Markdown output. Usually, the input files are reStructuredText, Markdown and AsciiDoc
files, and the output is a blog, but both input and output can be anything you files, and the output is a blog, but both input and output can be anything you
want. want.
@ -23,9 +23,9 @@ The logic is separated into different classes and concepts:
on. Since those operations are commonly used, the object is created once and on. Since those operations are commonly used, the object is created once and
then passed to the generators. then passed to the generators.
* **Readers** are used to read from various formats (Markdown and * **Readers** are used to read from various formats (AsciiDoc, Markdown and
reStructuredText for now, but the system is extensible). Given a file, they return reStructuredText for now, but the system is extensible). Given a file, they
metadata (author, tags, category, etc.) and content (HTML-formatted). return metadata (author, tags, category, etc.) and content (HTML-formatted).
* **Generators** generate the different outputs. For instance, Pelican comes with * **Generators** generate the different outputs. For instance, Pelican comes with
``ArticlesGenerator`` and ``PageGenerator``. Given a configuration, they can do ``ArticlesGenerator`` and ``PageGenerator``. Given a configuration, they can do

View file

@ -121,6 +121,8 @@ Setting name (default value) What doe
This templates need to use ``DIRECT_TEMPLATES`` setting This templates need to use ``DIRECT_TEMPLATES`` setting
`MARKDOWN_EXTENSIONS` (``['toc',]``) A list of any Markdown extensions you want to use. `MARKDOWN_EXTENSIONS` (``['toc',]``) A list of any Markdown extensions you want to use.
`ASCIIDOC_OPTIONS` (``[]``) A list of options to pass to asciidoc, see the `manpage
<http://www.methods.co.nz/asciidoc/manpage.html>`_
===================================================================== ===================================================================== ===================================================================== =====================================================================
.. [#] Default is the system locale. .. [#] Default is the system locale.

View file

@ -13,6 +13,11 @@ try:
from markdown import Markdown from markdown import Markdown
except ImportError: except ImportError:
Markdown = False # NOQA Markdown = False # NOQA
try:
from asciidocapi import AsciiDocAPI
asciidoc = True
except ImportError:
asciidoc = False
import re import re
from pelican.contents import Category, Tag, Author from pelican.contents import Category, Tag, Author
@ -162,6 +167,37 @@ class HtmlReader(Reader):
return content, metadata return content, metadata
class AsciiDocReader(Reader):
enabled = bool(asciidoc)
file_extensions = ['asc']
default_options = ["--no-header-footer", "-a newline=\\n"]
def read(self, filename):
"""Parse content and metadata of asciidoc files"""
from cStringIO import StringIO
text = StringIO(pelican_open(filename))
content = StringIO()
ad = AsciiDocAPI()
options = self.settings.get('ASCIIDOC_OPTIONS', [])
if isinstance(options, (str, unicode)):
options = [m.strip() for m in options.split(',')]
options = self.default_options + options
for o in options:
ad.options(*o.split())
ad.execute(text, content, backend="html4")
content = content.getvalue()
metadata = {}
for name, value in ad.asciidoc.document.attributes.items():
name = name.lower()
metadata[name] = self.process_metadata(name, value)
if 'doctitle' in metadata:
metadata['title'] = metadata['doctitle']
return content, metadata
_EXTENSIONS = {} _EXTENSIONS = {}
for cls in Reader.__subclasses__(): for cls in Reader.__subclasses__():

View file

@ -0,0 +1,12 @@
Test AsciiDoc File Header
=========================
:Author: Author O. Article
:Email: <author@nowhere.com>
:Date: 2011-09-15 09:05
:Category: Blog
:Tags: Linux, Python, Pelican
Used for pelican test
---------------------
The quick brown fox jumped over the lazy dog's back.

View file

@ -0,0 +1,9 @@
Test AsciiDoc File Header
=========================
Used for pelican test
---------------------
version {revision}
The quick brown fox jumped over the lazy dog's back.

View file

@ -109,3 +109,46 @@ class MdReaderTest(unittest.TestCase):
'<h3 id="level2">Level2</h3>' '<h3 id="level2">Level2</h3>'
self.assertEqual(content, expected) self.assertEqual(content, expected)
class AdReaderTest(unittest.TestCase):
@unittest.skipUnless(readers.asciidoc, "asciidoc isn't installed")
def test_article_with_asc_extension(self):
# test to ensure the asc extension is being processed by the correct reader
reader = readers.AsciiDocReader({})
content, metadata = reader.read(_filename('article_with_asc_extension.asc'))
expected = '<hr>\n<h2><a name="_used_for_pelican_test"></a>Used for pelican test</h2>\n'\
'<p>The quick brown fox jumped over the lazy dog&#8217;s back.</p>\n'
self.assertEqual(content, expected)
expected = {
'category': 'Blog',
'author': 'Author O. Article',
'title': 'Test AsciiDoc File Header',
'date': datetime.datetime(2011, 9, 15, 9, 5),
'tags': ['Linux', 'Python', 'Pelican'],
}
for key, value in expected.items():
self.assertEquals(value, metadata[key], key)
expected = {
'category': 'Blog',
'author': 'Author O. Article',
'title': 'Test AsciiDoc File Header',
'date': datetime.datetime(2011, 9, 15, 9, 5),
'tags': ['Linux', 'Python', 'Pelican'],
}
for key, value in expected.items():
self.assertEquals(value, metadata[key], key)
@unittest.skipUnless(readers.asciidoc, "asciidoc isn't installed")
def test_article_with_asc_options(self):
# test to ensure the ASCIIDOC_OPTIONS is being used
reader = readers.AsciiDocReader(dict(ASCIIDOC_OPTIONS=["-a revision=1.0.42"]))
content, metadata = reader.read(_filename('article_with_asc_options.asc'))
expected = '<hr>\n<h2><a name="_used_for_pelican_test"></a>Used for pelican test</h2>\n'\
'<p>version 1.0.42</p>\n'\
'<p>The quick brown fox jumped over the lazy dog&#8217;s back.</p>\n'
self.assertEqual(content, expected)