88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
AsciiDoc Reader
|
|
===============
|
|
|
|
This plugin allows you to use AsciiDoc to write your posts.
|
|
File extension should be ``.asc``, ``.adoc``, or ``asciidoc``.
|
|
"""
|
|
|
|
from pelican.readers import BaseReader
|
|
from pelican import signals
|
|
import os
|
|
import re
|
|
import subprocess
|
|
|
|
def call(cmd):
|
|
"""Calls a CLI command and returns the stdout as string."""
|
|
return subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()[0].decode('utf-8')
|
|
|
|
def default():
|
|
"""Attempt to find the default AsciiDoc utility."""
|
|
for cmd in ALLOWED_CMDS:
|
|
if len(call(cmd + " --help")):
|
|
return cmd
|
|
|
|
ALLOWED_CMDS = ["asciidoc", "asciidoctor"]
|
|
|
|
ENABLED = None != default()
|
|
|
|
class AsciiDocReader(BaseReader):
|
|
"""Reader for AsciiDoc files."""
|
|
|
|
enabled = ENABLED
|
|
file_extensions = ['asc', 'adoc', 'asciidoc']
|
|
default_options = ['--no-header-footer']
|
|
|
|
def read(self, source_path):
|
|
"""Parse content and metadata of AsciiDoc files."""
|
|
cmd = self._get_cmd()
|
|
content = ""
|
|
if cmd:
|
|
optlist = self.settings.get('ASCIIDOC_OPTIONS', []) + self.default_options
|
|
options = " ".join(optlist)
|
|
content = call("%s %s -o - %s" % (cmd, options, source_path))
|
|
metadata = self._read_metadata(source_path)
|
|
return content, metadata
|
|
|
|
def _get_cmd(self):
|
|
"""Returns the AsciiDoc utility command to use for rendering or None if
|
|
one cannot be found."""
|
|
if self.settings.get('ASCIIDOC_CMD') in ALLOWED_CMDS:
|
|
return self.settings.get('ASCIIDOC_CMD')
|
|
return default()
|
|
|
|
def _read_metadata(self, source_path):
|
|
"""Parses the AsciiDoc file at the given `source_path` and returns found
|
|
metadata."""
|
|
metadata = {}
|
|
with open(source_path) as fi:
|
|
prev = ""
|
|
for line in fi.readlines():
|
|
# Parse for doc title.
|
|
if 'title' not in metadata.keys():
|
|
title = ""
|
|
if line.startswith("= "):
|
|
title = line[2:].strip()
|
|
elif line.count("=") == len(prev.strip()):
|
|
title = prev.strip()
|
|
if title:
|
|
metadata['title'] = self.process_metadata('title', title)
|
|
|
|
# Parse for other metadata.
|
|
regexp = re.compile(r"^:[A-z]+:\s*[A-z0-9]")
|
|
if regexp.search(line):
|
|
toks = line.split(":", 2)
|
|
key = toks[1].strip().lower()
|
|
val = toks[2].strip()
|
|
metadata[key] = self.process_metadata(key, val)
|
|
prev = line
|
|
return metadata
|
|
|
|
def add_reader(readers):
|
|
for ext in AsciiDocReader.file_extensions:
|
|
readers.reader_classes[ext] = AsciiDocReader
|
|
|
|
def register():
|
|
signals.readers_init.connect(add_reader)
|