Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 332c8c7

Browse files
committedAug 23, 2015
Initial (broken) implementation of pelican post reading
Signed-off-by: Chris Warrick <kwpolska@gmail.com>
1 parent c69770f commit 332c8c7

File tree

3 files changed

+79
-16
lines changed

3 files changed

+79
-16
lines changed
 

‎nikola/plugin_categories.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ class PageCompiler(BasePlugin):
242242
friendly_name = ''
243243
demote_headers = False
244244
supports_onefile = True
245+
metadata_can_be_overridden = False
245246
default_metadata = {
246247
'title': '',
247248
'slug': '',
@@ -299,7 +300,7 @@ def get_compiler_extensions(self):
299300
return plugins
300301

301302

302-
class CompilerExtension(BasePlugin):
303+
class CompilerExtension(BasePgin):
303304

304305
"""An extension for a Nikola compiler.
305306

‎nikola/plugins/compile/rest/__init__.py

+70-13
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,20 @@
4141
from nikola.utils import unicode_str, get_logger, makedirs, write_metadata, STDERR_HANDLER
4242

4343

44+
DOCINFO_PELICAN_NIKOLA_MAPPING = {
45+
'modified': 'updated',
46+
'authors': 'author',
47+
'summary': 'description'
48+
}
49+
4450
class CompileRest(PageCompiler):
4551

4652
"""Compile reStructuredText into HTML."""
4753

4854
name = "rest"
4955
friendly_name = "reStructuredText"
5056
demote_headers = True
57+
metadata_can_be_overridden = True
5158
logger = None
5259

5360
def _read_extra_deps(self, post):
@@ -63,7 +70,7 @@ def register_extra_dependencies(self, post):
6370
"""Add dependency to post object to check .dep file."""
6471
post.add_dependency(lambda: self._read_extra_deps(post), 'fragment')
6572

66-
def compile_html_string(self, data, source_path=None, is_two_file=True):
73+
def compile_html_string(self, data, source_path=None, is_two_file=True, return_publisher=False):
6774
"""Compile reST into HTML strings."""
6875
# If errors occur, this will be added to the line number reported by
6976
# docutils so the line number matches the actual line number (off by
@@ -74,7 +81,10 @@ def compile_html_string(self, data, source_path=None, is_two_file=True):
7481
add_ln = len(m_data.splitlines()) + 1
7582

7683
default_template_path = os.path.join(os.path.dirname(__file__), 'template.txt')
77-
output, error_level, deps = rst2html(
84+
# TODO cache publisher in post object (which requires a ton of
85+
# refactoring, and might even need v8 and breaking tons of APIs) for
86+
# speed -- right now, we are publishing each post twice
87+
publisher = rst2html(
7888
data, settings_overrides={
7989
'initial_header_level': 1,
8090
'record_dependencies': True,
@@ -83,12 +93,16 @@ def compile_html_string(self, data, source_path=None, is_two_file=True):
8393
'syntax_highlight': 'short',
8494
'math_output': 'mathjax',
8595
'template': default_template_path,
86-
}, logger=self.logger, source_path=source_path, l_add_ln=add_ln, transforms=self.site.rst_transforms)
87-
if not isinstance(output, unicode_str):
88-
# To prevent some weird bugs here or there.
89-
# Original issue: empty files. `output` became a bytestring.
90-
output = output.decode('utf-8')
91-
return output, error_level, deps
96+
}, logger=self.logger, source_path=source_path, l_add_ln=add_ln, transforms=self.site.rst_transforms, return_publisher=True)
97+
if return_publisher:
98+
return publisher
99+
else:
100+
output, error_level, deps = rst_document_tuple(publisher)
101+
if not isinstance(output, unicode_str):
102+
# To prevent some weird bugs here or there.
103+
# Original issue: empty files. `output` became a bytestring.
104+
output = output.decode('utf-8')
105+
return output, error_level, deps
92106

93107
def compile_html(self, source, dest, is_two_file=True):
94108
"""Compile source file into HTML and save as dest."""
@@ -112,6 +126,41 @@ def compile_html(self, source, dest, is_two_file=True):
112126
else:
113127
return False
114128

129+
def read_metadata(self, post, file_metadata_regexp=None, unslugify_titles=False, lang=None):
130+
"""Read the metadata from a post, and return a metadata dict."""
131+
metadata = {}
132+
source = post.translated_source_path(lang)
133+
with io.open(source, 'r', encoding='utf-8') as in_file:
134+
data = in_file.read()
135+
# This is a bit of a cheat. The method is now abused to create a
136+
# publisher and not the full document tuple.
137+
publisher = self.compile_html_string(data, source, post.is_two_file, True)
138+
139+
# Get title.
140+
title_id = publisher.document.first_child_matching_class(docutils.nodes.title)
141+
if title_id is not None:
142+
metadata['title'] = publisher.document.children[title_id].astext()
143+
144+
# Get any other metadata that is part of the reST standard docinfo
145+
# (which is a special field list)
146+
docinfo_id = publisher.document.first_child_matching_class(docutils.nodes.docinfo)
147+
if docinfo_id is not None:
148+
docinfo = publisher.document.children[docinfo_id]
149+
for field in docinfo.children:
150+
fieldname = field.tagname
151+
if fieldname == 'authors':
152+
field.child_text_separator = ', '
153+
fieldvalue = field.astext()
154+
elif fieldname == 'field':
155+
fieldname = field.children[0].astext()
156+
fieldvalue = field.children[1].astext()
157+
else:
158+
fieldvalue = field.astext()
159+
fieldname = fieldname.lower()
160+
fieldname = DOCINFO_PELICAN_NIKOLA_MAPPING.get(fieldname, fieldname)
161+
metadata[fieldname] = fieldvalue
162+
return metadata
163+
115164
def create_post(self, path, **kw):
116165
"""Create a new post."""
117166
content = kw.pop('content', None)
@@ -237,11 +286,8 @@ def rst2html(source, source_path=None, source_class=docutils.io.StringInput,
237286
parser=None, parser_name='restructuredtext', writer=None,
238287
writer_name='html', settings=None, settings_spec=None,
239288
settings_overrides=None, config_section=None,
240-
enable_exit_status=None, logger=None, l_add_ln=0, transforms=None):
241-
"""Set up & run a ``Publisher``, and return a dictionary of document parts.
242-
243-
Dictionary keys are the names of parts, and values are Unicode strings;
244-
encoding is up to the client. For programmatic use with string I/O.
289+
enable_exit_status=None, logger=None, l_add_ln=0, transforms=None, return_publisher=False):
290+
"""Set up & run a ``Publisher``, and return the publisher or the document.
245291
246292
For encoded string input, be sure to set the 'input_encoding' setting to
247293
the desired encoding. Set it to 'unicode' for unencoded Unicode string
@@ -275,4 +321,15 @@ def rst2html(source, source_path=None, source_class=docutils.io.StringInput,
275321
pub.set_destination(None, destination_path)
276322
pub.publish(enable_exit_status=enable_exit_status)
277323

324+
if return_publisher:
325+
return pub
326+
else:
327+
return rst_document_tuple(pub)
328+
329+
330+
def rst_document_tuple(pub):
331+
"""Return the document tuple (output, error level, dependencies) for a publisher.
332+
333+
Previously, the only output of rst2html.
334+
"""
278335
return pub.writer.parts['docinfo'] + pub.writer.parts['fragment'], pub.document.reporter.max_level, pub.settings.record_dependencies

‎nikola/post.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ def wrap_encrypt(path, password):
486486
self.compile_html(
487487
self.translated_source_path(lang),
488488
dest,
489-
self.is_two_file),
489+
self.is_two_file)
490490
if self.meta('password'):
491491
# TODO: get rid of this feature one day (v8?; warning added in v7.3.0.)
492492
LOGGER.warn("The post {0} is using the `password` attribute, which may stop working in the future.")
@@ -989,8 +989,13 @@ def get_meta(post, file_metadata_regexp=None, unslugify_titles=False, lang=None)
989989
if getattr(post, 'compiler', None):
990990
compiler_meta = post.compiler.read_metadata(post, file_metadata_regexp, unslugify_titles, lang)
991991
meta.update(compiler_meta)
992+
if compiler_meta:
993+
compiler_meta_override = post.compiler.metadata_can_be_overridden
994+
else:
995+
compiler_meta_override = True
996+
992997

993-
if not post.is_two_file and not compiler_meta:
998+
if not post.is_two_file and compiler_meta_override:
994999
# Meta file has precedence over file, which can contain garbage.
9951000
# Moreover, we should not to talk to the file if we have compiler meta.
9961001
meta.update(get_metadata_from_file(post.source_path, config, lang))

0 commit comments

Comments
 (0)
Please sign in to comment.