Init
This commit is contained in:
commit
9e0019a728
1
__init__.py
Normal file
1
__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .asciidoctor import *
|
181
asciidoctor.py
Normal file
181
asciidoctor.py
Normal file
@ -0,0 +1,181 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
AsciiDoctor
|
||||
===========
|
||||
|
||||
This plugin allows you to use AsciiDoctor to write your posts.
|
||||
File extension should be ``.asc``, ``.adoc``, or ``asciidoc``.
|
||||
|
||||
This plugin is based on
|
||||
https://github.com/getpelican/pelican-plugins/tree/master/asciidoc_reader
|
||||
and
|
||||
https://github.com/marienfressinaud/Pelidoc
|
||||
|
||||
"""
|
||||
|
||||
from pelican.readers import BaseReader
|
||||
from pelican.generators import Generator
|
||||
from pelican import signals
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import logging
|
||||
from subprocess import check_call, check_output
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
pattern = re.compile("Asciidoctor.*asciidoctor.org")
|
||||
|
||||
class AsciiDoctorReader(BaseReader):
|
||||
""" Reader for AsciiDoc files. """
|
||||
|
||||
file_extensions = ['asc', 'adoc', 'asciidoc']
|
||||
|
||||
def read(self, source_path):
|
||||
"""Parse content and metadata of AsciiDoc files."""
|
||||
cmd = self.settings.get('ASCIIDOCTOR_CMD', 'asciidoctor')
|
||||
cmd_version = check_output(['asciidoctor', '--version']).decode('utf-8')
|
||||
if not pattern.match(cmd_version):
|
||||
logger.error("AsciiDoctorReader: {} is not asciidoctor executable".format(cmd))
|
||||
return
|
||||
|
||||
content = ""
|
||||
if cmd:
|
||||
content = check_output(
|
||||
[cmd] + self.settings.get('ASCIIDOCTOR_EXTRA_OPTIONS', []) +
|
||||
['--doctype=article'] + ['--no-header-footer'] +
|
||||
['--out-file', '-', source_path]
|
||||
).decode('utf-8')
|
||||
metadata = self._read_metadata(source_path)
|
||||
return content, metadata
|
||||
|
||||
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)
|
||||
|
||||
regexp = re.compile(r"^:[\-A-z]+:\s*")
|
||||
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
|
||||
if (not 'summary' in metadata) or (metadata['summary'] is None):
|
||||
metadata['summary'] = ''
|
||||
return metadata
|
||||
|
||||
|
||||
class AsciiDoctorPdfGenerator(Generator):
|
||||
"""The AsciiDoctorPdf generator.
|
||||
"""
|
||||
|
||||
def guess_format(self, content):
|
||||
"""Return the format used by a given content.
|
||||
"""
|
||||
|
||||
formats = {
|
||||
'.adoc': 'asciidoc',
|
||||
'.asciidoc': 'asciidoc',
|
||||
'.asc': 'asciidoc',
|
||||
}
|
||||
|
||||
file_name, file_extension = os.path.splitext(content.source_path)
|
||||
|
||||
return formats[file_extension]
|
||||
|
||||
def check_output_dir(self, dir_):
|
||||
"""Check and create if needed the given directory."""
|
||||
if not os.path.isdir(dir_):
|
||||
try:
|
||||
os.mkdir(dir_)
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def generate_files(self, content):
|
||||
"""Generates the list of files for a given content.
|
||||
|
||||
:param content: the content to generate.
|
||||
:type content: pelican.contents.Content
|
||||
|
||||
"""
|
||||
|
||||
cmd = self.settings.get('ASCIIDOCTOR_CMD', 'asciidoctor')
|
||||
cmd_version = check_output(['asciidoctor', '--version']).decode('utf-8')
|
||||
if not pattern.match(cmd_version):
|
||||
logger.error("AsciiDoctorPdfGenerator: {} is not asciidoctor executable".format(cmd))
|
||||
return
|
||||
|
||||
if self.settings.get('PDF_PROCESSOR', False) == False:
|
||||
return
|
||||
|
||||
try:
|
||||
from_format = self.guess_format(content)
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
list_outputs = self.settings.get('ASCIIDOCTOR_PDF_OUTPUT_DIR', 'pdf')
|
||||
output_dir = os.path.join(self.output_path, list_outputs)
|
||||
|
||||
if not self.check_output_dir(output_dir):
|
||||
logger.error("Couldn't create the PDF output "
|
||||
"folder in {dir}".format(dir=output_dir))
|
||||
return
|
||||
|
||||
filename = "{id_file}.pdf".format(id_file=content.slug)
|
||||
filepath = os.path.join(output_dir, filename)
|
||||
|
||||
check_call([cmd] + self.settings.get('ASCIIDOCTOR_EXTRA_OPTIONS', []) +
|
||||
['--require', 'asciidoctor-pdf', '--backend', 'pdf'] +
|
||||
['--doctype=article'] +
|
||||
['--out-file', filepath, content.source_path])
|
||||
|
||||
logger.info("[ok] writing {filepath}".format(filepath=filepath))
|
||||
|
||||
def generate_output(self, writer=None):
|
||||
"""Generate files for each articles and pages.
|
||||
|
||||
If ASCIIDOCTOR_EXPORT_ARTICLES is False, articles are not generated.
|
||||
If ASCIIDOCTOR_EXPORT_PAGES is False, pages are not generated.
|
||||
|
||||
We don't use the writer passed as argument since we write our own
|
||||
files ((c) PDF plugin :)).
|
||||
|
||||
"""
|
||||
contents_to_export = []
|
||||
if self.settings.get('ASCIIDOCTOR_EXPORT_ARTICLES', True):
|
||||
contents_to_export += self.context['articles']
|
||||
|
||||
if self.settings.get('ASCIIDOCTOR_EXPORT_PAGES', True):
|
||||
contents_to_export += self.context['pages']
|
||||
|
||||
for content_to_export in contents_to_export:
|
||||
self.generate_files(content_to_export)
|
||||
|
||||
|
||||
def add_reader(readers):
|
||||
for ext in AsciiDoctorReader.file_extensions:
|
||||
readers.reader_classes[ext] = AsciiDoctorReader
|
||||
|
||||
|
||||
def get_generator(generator):
|
||||
return AsciiDoctorPdfGenerator
|
||||
|
||||
|
||||
def register():
|
||||
signals.readers_init.connect(add_reader)
|
||||
signals.get_generators.connect(get_generator)
|
Loading…
Reference in New Issue
Block a user