123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- """
- Org Reader
- ==========
- Version 1.1.
- Relevant Pelican settings:
- - ORG_READER_EMACS_LOCATION: Required. Location of Emacs binary.
- - ORG_READER_EMACS_SETTINGS: Optional. An absolute path to an Elisp file, to
- run per invocation. Useful for initializing the `package` Emacs library if
- that's where your Org mode comes from, or any modifications to Org Export-
- related variables.
- - ORG_READER_BACKEND: Optional. A custom backend to provide to Org. Defaults
- to 'html.
- To provide metadata to Pelican, the following properties can be defined in
- the org file's header:
- #+TITLE: The Title Of This BlogPost
- #+DATE: 2001-01-01
- #+CATEGORY: blog-category
- #+AUTHOR: My Name
- #+PROPERTY: LANGUAGE en
- #+PROPERTY: SUMMARY hello, this is the description
- #+PROPERTY: SLUG test_slug
- #+PROPERTY: MODIFIED [2015-12-29 Di]
- #+PROPERTY: TAGS my, first, tags
- #+PROPERTY: SAVE_AS alternative_filename.html
- - The TITLE is the only mandatory header property
- - Timestamps (DATE and MODIFIED) are optional and can be either a string of
- %Y-%m-%d or an org timestamp
- - The property names (SUMMARY, SLUG, MODIFIED, TAGS, SAVE_AS) can be either
- lower-case or upper-case
- - The slug is automatically the filename of the Org file, if not explicitly
- specified
- - It is not possible to pass an empty property to Pelican. For this plugin,
- it makes no difference if a property is present in the Org file and left
- empty, or if it is not defined at all.
- """
- import os
- import json
- import logging
- import subprocess
- from pelican import readers
- from pelican import signals
- ELISP = os.path.join(os.path.dirname(__file__), 'org_reader.el')
- LOG = logging.getLogger(__name__)
- class OrgReader(readers.BaseReader):
- enabled = True
- EMACS_ARGS = ["-Q", "--batch"]
- ELISP_EXEC = "(org->pelican \"{0}\" {1})"
- file_extensions = ['org']
- def __init__(self, settings):
- super(OrgReader, self).__init__(settings)
- assert 'ORG_READER_EMACS_LOCATION' in self.settings, \
- "No ORG_READER_EMACS_LOCATION specified in settings"
- def read(self, filename):
- LOG.info("Reading Org file {0}".format(filename))
- cmd = [self.settings['ORG_READER_EMACS_LOCATION']]
- cmd.extend(self.EMACS_ARGS)
- if 'ORG_READER_EMACS_SETTINGS' in self.settings:
- cmd.append('-l')
- cmd.append(self.settings['ORG_READER_EMACS_SETTINGS'])
- backend = self.settings.get('ORG_READER_BACKEND', "'html")
- cmd.append('-l')
- cmd.append(ELISP)
- cmd.append('--eval')
- cmd.append(self.ELISP_EXEC.format(filename, backend))
- LOG.debug("OrgReader: running command `{0}`".format(cmd))
- json_result = subprocess.check_output(cmd, universal_newlines=True)
- json_output = json.loads(json_result)
- # get default slug from .org filename
- default_slug, _ = os.path.splitext(os.path.basename(filename))
- metadata = {'title': json_output['title'] or '',
- 'date': json_output['date'] or '',
- 'author': json_output['author'] or '',
- 'lang': json_output['language'] or '',
- 'category': json_output['category'] or '',
- 'slug': json_output['slug'] or default_slug,
- 'modified': json_output['modified'] or '',
- 'tags': json_output['tags'] or '',
- 'save_as': json_output['save_as'] or '',
- 'summary': json_output['summary'] or ''}
- # remove empty strings when necessary
- for key in ['save_as', 'modified', 'lang', 'summary']:
- if not metadata[key]:
- metadata.pop(key)
- parsed = {}
- for key, value in metadata.items():
- parsed[key] = self.process_metadata(key, value)
- content = json_output['post']
- return content, parsed
- def add_reader(readers):
- readers.reader_classes['org'] = OrgReader
- def register():
- signals.readers_init.connect(add_reader)
|