updated deploy to call git pull first
16
conf.py
|
|
@ -16,14 +16,14 @@ NAVIGATION_LINKS = {
|
|||
('/stories/about.html', 'About me'),
|
||||
('/stories/privacy.html', 'Privacy'),
|
||||
('/photos/', 'Photos'),
|
||||
#(
|
||||
#(
|
||||
#('http://www.donaldharper.com', 'My Photo Blog'),
|
||||
#('http://p365.donaldharper.com', 'My Attempt at a Project 365'),
|
||||
#('http://www.duckland.org', 'My Personal and Tech Blog'),
|
||||
#),
|
||||
#'My Sites'
|
||||
#),
|
||||
(
|
||||
(
|
||||
#('http://www.donaldharper.com', 'My Photo Blog'),
|
||||
('http://p365.donaldharper.com', 'My Attempt at a Project 365'),
|
||||
('http://www.duckland.org', 'My Personal and Tech Blog'),
|
||||
),
|
||||
'My Sites'
|
||||
),
|
||||
(
|
||||
(
|
||||
('https://twitter.com/duckunix', 'My Twitter'),
|
||||
|
|
|
|||
BIN
images/Christmas-2016/Santa-Train.jpg
Normal file
|
After Width: | Height: | Size: 3.4 MiB |
|
|
@ -1,9 +0,0 @@
|
|||
This plugin will do a quick and dirty import of any RSS or Atom feed into Nikola
|
||||
|
||||
To use it:
|
||||
|
||||
```
|
||||
$ nikola plugin -i import_feed
|
||||
$ nikola import_feed --url=feed_url
|
||||
```
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
PAGES = (
|
||||
("stories/*.html", "stories", "story.tmpl"),
|
||||
)
|
||||
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
[Core]
|
||||
Name = import_feed
|
||||
Module = import_feed
|
||||
|
||||
[Documentation]
|
||||
Author = Grzegorz Śliwiński
|
||||
Version = 0.2
|
||||
Website = http://www.fizyk.net.pl/
|
||||
Description = Import a blog posts from a RSS/Atom feed
|
||||
|
||||
|
|
@ -1,217 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright © 2012-2014 Roberto Alsina and others.
|
||||
|
||||
# Permission is hereby granted, free of charge, to any
|
||||
# person obtaining a copy of this software and associated
|
||||
# documentation files (the "Software"), to deal in the
|
||||
# Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the
|
||||
# Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice
|
||||
# shall be included in all copies or substantial portions of
|
||||
# the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
import datetime
|
||||
import os
|
||||
import time
|
||||
|
||||
try:
|
||||
from urlparse import urlparse
|
||||
except ImportError:
|
||||
from urllib.parse import urlparse # NOQA
|
||||
|
||||
try:
|
||||
import feedparser
|
||||
except ImportError:
|
||||
feedparser = None # NOQA
|
||||
|
||||
from nikola.plugin_categories import Command
|
||||
from nikola import utils
|
||||
from nikola.utils import req_missing
|
||||
from nikola.plugins.basic_import import ImportMixin
|
||||
from nikola.plugins.command.init import SAMPLE_CONF, prepare_config
|
||||
|
||||
LOGGER = utils.get_logger('import_feed', utils.STDERR_HANDLER)
|
||||
|
||||
|
||||
class CommandImportFeed(Command, ImportMixin):
|
||||
"""Import a feed dump."""
|
||||
|
||||
name = "import_feed"
|
||||
needs_config = False
|
||||
doc_usage = "[options] --url=feed_url"
|
||||
doc_purpose = "import a RSS/Atom feed"
|
||||
cmd_options = [
|
||||
{
|
||||
'name': 'output_folder',
|
||||
'long': 'output-folder',
|
||||
'short': 'o',
|
||||
'default': 'new_site',
|
||||
'help': 'Location to write imported content.'
|
||||
},
|
||||
{
|
||||
'name': 'url',
|
||||
'long': 'url',
|
||||
'short': 'u',
|
||||
'default': None,
|
||||
'help': 'URL or filename of the feed to be imported.'
|
||||
},
|
||||
]
|
||||
|
||||
def _execute(self, options, args):
|
||||
'''
|
||||
Import Atom/RSS feed
|
||||
'''
|
||||
if feedparser is None:
|
||||
req_missing(['feedparser'], 'import feeds')
|
||||
return
|
||||
|
||||
if not options['url']:
|
||||
print(self.help())
|
||||
return
|
||||
|
||||
self.feed_url = options['url']
|
||||
self.output_folder = options['output_folder']
|
||||
self.import_into_existing_site = False
|
||||
self.url_map = {}
|
||||
channel = self.get_channel_from_file(self.feed_url)
|
||||
self.context = self.populate_context(channel)
|
||||
conf_template = self.generate_base_site()
|
||||
self.context['REDIRECTIONS'] = self.configure_redirections(
|
||||
self.url_map)
|
||||
|
||||
self.import_posts(channel)
|
||||
|
||||
self.write_configuration(self.get_configuration_output_path(
|
||||
), conf_template.render(**prepare_config(self.context)))
|
||||
|
||||
@classmethod
|
||||
def get_channel_from_file(cls, filename):
|
||||
return feedparser.parse(filename)
|
||||
|
||||
@staticmethod
|
||||
def populate_context(channel):
|
||||
context = SAMPLE_CONF.copy()
|
||||
context['DEFAULT_LANG'] = channel.feed.title_detail.language \
|
||||
if channel.feed.title_detail.language else 'en'
|
||||
context['BLOG_TITLE'] = channel.feed.title
|
||||
|
||||
context['BLOG_DESCRIPTION'] = channel.feed.get('subtitle', '')
|
||||
context['SITE_URL'] = channel.feed.get('link', '').rstrip('/')
|
||||
context['BLOG_EMAIL'] = channel.feed.author_detail.get('email', '') if 'author_detail' in channel.feed else ''
|
||||
context['BLOG_AUTHOR'] = channel.feed.author_detail.get('name', '') if 'author_detail' in channel.feed else ''
|
||||
|
||||
context['POSTS'] = '''(
|
||||
("posts/*.html", "posts", "post.tmpl"),
|
||||
)'''
|
||||
context['PAGES'] = '''(
|
||||
("stories/*.html", "stories", "story.tmpl"),
|
||||
)'''
|
||||
context['COMPILERS'] = '''{
|
||||
"rest": ('.txt', '.rst'),
|
||||
"markdown": ('.md', '.mdown', '.markdown', '.wp'),
|
||||
"html": ('.html', '.htm')
|
||||
}
|
||||
'''
|
||||
|
||||
return context
|
||||
|
||||
def import_posts(self, channel):
|
||||
for item in channel.entries:
|
||||
self.process_item(item)
|
||||
|
||||
def process_item(self, item):
|
||||
self.import_item(item, 'posts')
|
||||
|
||||
def import_item(self, item, out_folder=None):
|
||||
"""Takes an item from the feed and creates a post file."""
|
||||
if out_folder is None:
|
||||
out_folder = 'posts'
|
||||
|
||||
# link is something like http://foo.com/2012/09/01/hello-world/
|
||||
# So, take the path, utils.slugify it, and that's our slug
|
||||
link = item.link
|
||||
link_path = urlparse(link).path
|
||||
|
||||
title = item.title
|
||||
|
||||
# blogger supports empty titles, which Nikola doesn't
|
||||
if not title:
|
||||
LOGGER.warn("Empty title in post with URL {0}. Using NO_TITLE "
|
||||
"as placeholder, please fix.".format(link))
|
||||
title = "NO_TITLE"
|
||||
|
||||
if link_path.lower().endswith('.html'):
|
||||
link_path = link_path[:-5]
|
||||
|
||||
slug = utils.slugify(link_path)
|
||||
|
||||
if not slug: # should never happen
|
||||
LOGGER.error("Error converting post:", title)
|
||||
return
|
||||
|
||||
description = ''
|
||||
post_date = datetime.datetime.fromtimestamp(time.mktime(
|
||||
item.published_parsed))
|
||||
if item.get('content'):
|
||||
for candidate in item.get('content', []):
|
||||
content = candidate.value
|
||||
break
|
||||
# FIXME: handle attachments
|
||||
elif item.get('summary'):
|
||||
content = item.get('summary')
|
||||
else:
|
||||
content = ''
|
||||
LOGGER.warn('Entry without content! {}', item)
|
||||
|
||||
tags = []
|
||||
for tag in item.get('tags', []):
|
||||
tags.append(tag.term)
|
||||
|
||||
if item.get('app_draft'):
|
||||
tags.append('draft')
|
||||
is_draft = True
|
||||
else:
|
||||
is_draft = False
|
||||
|
||||
self.url_map[link] = self.context['SITE_URL'] + '/' + \
|
||||
out_folder + '/' + slug + '.html'
|
||||
|
||||
if is_draft and self.exclude_drafts:
|
||||
LOGGER.notice('Draft "{0}" will not be imported.'.format(title))
|
||||
elif content.strip():
|
||||
# If no content is found, no files are written.
|
||||
content = self.transform_content(content)
|
||||
|
||||
self.write_metadata(os.path.join(self.output_folder, out_folder,
|
||||
slug + '.meta'),
|
||||
title, slug, post_date, description, tags)
|
||||
self.write_content(
|
||||
os.path.join(self.output_folder, out_folder, slug + '.html'),
|
||||
content)
|
||||
else:
|
||||
LOGGER.warn('Not going to import "{0}" because it seems to contain'
|
||||
' no content.'.format(title))
|
||||
|
||||
@staticmethod
|
||||
def write_metadata(filename, title, slug, post_date, description, tags):
|
||||
ImportMixin.write_metadata(filename,
|
||||
title,
|
||||
slug,
|
||||
post_date.strftime(r'%Y/%m/%d %H:%m:%S'),
|
||||
description,
|
||||
tags)
|
||||
|
|
@ -1 +0,0 @@
|
|||
feedparser
|
||||
|
|
@ -1 +0,0 @@
|
|||
feedparser
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
Modified version of original reST plugin that uses an [alternative docutils writer](https://bitbucket.org/andre_felipe_dias/rst2html5) to produce HTML5 output.
|
||||
|
||||
**Note:** if you want to use the Nikola-provided reST extensions, you need to
|
||||
keep the original `rest` compiler in COMPILERS *and* POSTS/PAGES, otherwise
|
||||
they will not get loaded.
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
COMPILERS = {
|
||||
'rest': ('.rst4',),
|
||||
'rest_html5': ('.rst', '.txt'),
|
||||
}
|
||||
|
||||
POSTS = (
|
||||
("posts/*.rst4", "posts", "post.tmpl"),
|
||||
("posts/*.rst", "posts", "post.tmpl"),
|
||||
("posts/*.txt", "posts", "post.tmpl"),
|
||||
)
|
||||
|
||||
# NOTE: if you want to use the Nikola-provided reST extensions, you need to
|
||||
# keep the original `rest` compiler in COMPILERS *and* POSTS/PAGES,
|
||||
# otherwise they will not get loaded.
|
||||
|
|
@ -1 +0,0 @@
|
|||
rst2html5
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
[Core]
|
||||
Name = rest_html5
|
||||
Module = rest_html5
|
||||
|
||||
[Documentation]
|
||||
Author = Roberto Alsina, Pelle Nilsson
|
||||
Version = 1.0.1
|
||||
Website = http://plugins.getnikola.com/#rest_html5
|
||||
Description = Compile reST into HTML5
|
||||
|
||||
|
|
@ -1,280 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright © 2012-2015 Roberto Alsina and others.
|
||||
|
||||
# Permission is hereby granted, free of charge, to any
|
||||
# person obtaining a copy of this software and associated
|
||||
# documentation files (the "Software"), to deal in the
|
||||
# Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the
|
||||
# Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice
|
||||
# shall be included in all copies or substantial portions of
|
||||
# the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
|
||||
try:
|
||||
import docutils.core
|
||||
import docutils.nodes
|
||||
import docutils.utils
|
||||
import docutils.io
|
||||
import docutils.readers.standalone
|
||||
has_docutils = True
|
||||
except ImportError:
|
||||
has_docutils = False
|
||||
|
||||
try:
|
||||
import rst2html5
|
||||
has_rst2html5 = True
|
||||
except ImportError:
|
||||
has_rst2html5 = False
|
||||
|
||||
from nikola.plugin_categories import PageCompiler
|
||||
from nikola.utils import get_logger, makedirs, req_missing, write_metadata
|
||||
|
||||
|
||||
class CompileRestHTML5(PageCompiler):
|
||||
"""Compile reSt into HTML."""
|
||||
|
||||
name = "rest_html5"
|
||||
demote_headers = True
|
||||
logger = None
|
||||
|
||||
def _read_extra_deps(self, post):
|
||||
"""Reads contents of .dep file and returns them as a list"""
|
||||
dep_path = post.base_path + '.dep'
|
||||
if os.path.isfile(dep_path):
|
||||
with io.open(dep_path, 'r+', encoding='utf8') as depf:
|
||||
deps = [l.strip() for l in depf.readlines()]
|
||||
return deps
|
||||
return []
|
||||
|
||||
def register_extra_dependencies(self, post):
|
||||
"""Adds dependency to post object to check .dep file."""
|
||||
post.add_dependency(lambda: self._read_extra_deps(post), 'fragment')
|
||||
|
||||
def compile_html(self, source, dest, is_two_file=True):
|
||||
"""Compile reSt into HTML."""
|
||||
|
||||
if not has_docutils:
|
||||
req_missing(['docutils'], 'build this site (compile reStructuredText)')
|
||||
if not has_rst2html5:
|
||||
req_missing(['rst2html5'], 'build this site (compile reStructuredText into HTML5)')
|
||||
makedirs(os.path.dirname(dest))
|
||||
error_level = 100
|
||||
with io.open(dest, "w+", encoding="utf8") as out_file:
|
||||
with io.open(source, "r", encoding="utf8") as in_file:
|
||||
data = in_file.read()
|
||||
add_ln = 0
|
||||
if not is_two_file:
|
||||
spl = re.split('(\n\n|\r\n\r\n)', data, maxsplit=1)
|
||||
data = spl[-1]
|
||||
if len(spl) != 1:
|
||||
# If errors occur, this will be added to the line
|
||||
# number reported by docutils so the line number
|
||||
# matches the actual line number (off by 7 with default
|
||||
# metadata, could be more or less depending on the post
|
||||
# author).
|
||||
add_ln = len(spl[0].splitlines()) + 1
|
||||
|
||||
default_template_path = os.path.join(os.path.dirname(__file__), 'template.txt')
|
||||
output, error_level, deps = rst2html(
|
||||
data, settings_overrides={
|
||||
'initial_header_level': 0,
|
||||
'record_dependencies': True,
|
||||
'stylesheet_path': None,
|
||||
'link_stylesheet': True,
|
||||
'syntax_highlight': 'short',
|
||||
'math_output': 'mathjax',
|
||||
'template': default_template_path,
|
||||
}, logger=self.logger, source_path=source, l_add_ln=add_ln)
|
||||
out_file.write(output)
|
||||
deps_path = dest + '.dep'
|
||||
if deps.list:
|
||||
with io.open(deps_path, "w+", encoding="utf8") as deps_file:
|
||||
deps_file.write('\n'.join(deps.list))
|
||||
else:
|
||||
if os.path.isfile(deps_path):
|
||||
os.unlink(deps_path)
|
||||
if error_level < 3:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def create_post(self, path, **kw):
|
||||
content = kw.pop('content', None)
|
||||
onefile = kw.pop('onefile', False)
|
||||
# is_page is not used by create_post as of now.
|
||||
kw.pop('is_page', False)
|
||||
metadata = {}
|
||||
metadata.update(self.default_metadata)
|
||||
metadata.update(kw)
|
||||
makedirs(os.path.dirname(path))
|
||||
if not content.endswith('\n'):
|
||||
content += '\n'
|
||||
with io.open(path, "w+", encoding="utf8") as fd:
|
||||
if onefile:
|
||||
fd.write(write_metadata(metadata))
|
||||
fd.write('\n')
|
||||
fd.write(content)
|
||||
|
||||
def set_site(self, site):
|
||||
self.config_dependencies = []
|
||||
for plugin_info in site.plugin_manager.getPluginsOfCategory("RestExtension"):
|
||||
if plugin_info.name in site.config['DISABLED_PLUGINS']:
|
||||
site.plugin_manager.removePluginFromCategory(plugin_info, "RestExtension")
|
||||
continue
|
||||
|
||||
site.plugin_manager.activatePluginByName(plugin_info.name)
|
||||
self.config_dependencies.append(plugin_info.name)
|
||||
plugin_info.plugin_object.set_site(site)
|
||||
plugin_info.plugin_object.short_help = plugin_info.description
|
||||
|
||||
self.logger = get_logger('compile_rest', site.loghandlers)
|
||||
if not site.debug:
|
||||
self.logger.level = 4
|
||||
|
||||
return super(CompileRestHTML5, self).set_site(site)
|
||||
|
||||
|
||||
def get_observer(settings):
|
||||
"""Return an observer for the docutils Reporter."""
|
||||
def observer(msg):
|
||||
"""Report docutils/rest messages to a Nikola user.
|
||||
|
||||
Error code mapping:
|
||||
|
||||
+------+---------+------+----------+
|
||||
| dNUM | dNAME | lNUM | lNAME | d = docutils, l = logbook
|
||||
+------+---------+------+----------+
|
||||
| 0 | DEBUG | 1 | DEBUG |
|
||||
| 1 | INFO | 2 | INFO |
|
||||
| 2 | WARNING | 4 | WARNING |
|
||||
| 3 | ERROR | 5 | ERROR |
|
||||
| 4 | SEVERE | 6 | CRITICAL |
|
||||
+------+---------+------+----------+
|
||||
"""
|
||||
errormap = {0: 1, 1: 2, 2: 4, 3: 5, 4: 6}
|
||||
text = docutils.nodes.Element.astext(msg)
|
||||
line = msg['line'] + settings['add_ln'] if 'line' in msg else 0
|
||||
out = '[{source}{colon}{line}] {text}'.format(
|
||||
source=settings['source'], colon=(':' if line else ''),
|
||||
line=line, text=text)
|
||||
settings['logger'].log(errormap[msg['level']], out)
|
||||
|
||||
return observer
|
||||
|
||||
|
||||
class NikolaReader(docutils.readers.standalone.Reader):
|
||||
|
||||
def new_document(self):
|
||||
"""Create and return a new empty document tree (root node)."""
|
||||
document = docutils.utils.new_document(self.source.source_path, self.settings)
|
||||
document.reporter.stream = False
|
||||
document.reporter.attach_observer(get_observer(self.l_settings))
|
||||
return document
|
||||
|
||||
|
||||
def add_node(node, visit_function=None, depart_function=None):
|
||||
"""
|
||||
Register a Docutils node class.
|
||||
This function is completely optional. It is a same concept as
|
||||
`Sphinx add_node function <http://sphinx-doc.org/ext/appapi.html#sphinx.application.Sphinx.add_node>`_.
|
||||
|
||||
For example::
|
||||
|
||||
class Plugin(RestExtension):
|
||||
|
||||
name = "rest_math"
|
||||
|
||||
def set_site(self, site):
|
||||
self.site = site
|
||||
directives.register_directive('math', MathDirective)
|
||||
add_node(MathBlock, visit_Math, depart_Math)
|
||||
return super(Plugin, self).set_site(site)
|
||||
|
||||
class MathDirective(Directive):
|
||||
def run(self):
|
||||
node = MathBlock()
|
||||
return [node]
|
||||
|
||||
class Math(docutils.nodes.Element): pass
|
||||
|
||||
def visit_Math(self, node):
|
||||
self.body.append(self.starttag(node, 'math'))
|
||||
|
||||
def depart_Math(self, node):
|
||||
self.body.append('</math>')
|
||||
|
||||
For full example, you can refer to `Microdata plugin <http://plugins.getnikola.com/#microdata>`_
|
||||
"""
|
||||
docutils.nodes._add_node_class_names([node.__name__])
|
||||
if visit_function:
|
||||
setattr(rst2html5.HTML5Translator, 'visit_' + node.__name__, visit_function)
|
||||
if depart_function:
|
||||
setattr(rst2html5.HTML5Translator, 'depart_' + node.__name__, depart_function)
|
||||
|
||||
|
||||
def rst2html(source, source_path=None, source_class=docutils.io.StringInput,
|
||||
destination_path=None, reader=None,
|
||||
parser=None, parser_name='restructuredtext', writer=None,
|
||||
writer_name='html5', settings=None, settings_spec=None,
|
||||
settings_overrides=None, config_section=None,
|
||||
enable_exit_status=None, logger=None, l_add_ln=0):
|
||||
"""
|
||||
Set up & run a `Publisher`, and return a dictionary of document parts.
|
||||
Dictionary keys are the names of parts, and values are Unicode strings;
|
||||
encoding is up to the client. For programmatic use with string I/O.
|
||||
|
||||
For encoded string input, be sure to set the 'input_encoding' setting to
|
||||
the desired encoding. Set it to 'unicode' for unencoded Unicode string
|
||||
input. Here's how::
|
||||
|
||||
publish_parts(..., settings_overrides={'input_encoding': 'unicode'})
|
||||
|
||||
Parameters: see `publish_programmatically`.
|
||||
|
||||
WARNING: `reader` should be None (or NikolaReader()) if you want Nikola to report
|
||||
reStructuredText syntax errors.
|
||||
"""
|
||||
if reader is None:
|
||||
reader = NikolaReader()
|
||||
# For our custom logging, we have special needs and special settings we
|
||||
# specify here.
|
||||
# logger a logger from Nikola
|
||||
# source source filename (docutils gets a string)
|
||||
# add_ln amount of metadata lines (see comment in compile_html above)
|
||||
reader.l_settings = {'logger': logger, 'source': source_path,
|
||||
'add_ln': l_add_ln}
|
||||
|
||||
if writer is None:
|
||||
writer = rst2html5.HTML5Writer()
|
||||
|
||||
pub = docutils.core.Publisher(reader, parser, writer, settings=settings,
|
||||
source_class=source_class,
|
||||
destination_class=docutils.io.StringOutput)
|
||||
pub.set_components(None, parser_name, writer_name)
|
||||
pub.process_programmatic_settings(
|
||||
settings_spec, settings_overrides, config_section)
|
||||
pub.set_source(source, None)
|
||||
pub.settings._nikola_source_path = source_path
|
||||
pub.set_destination(None, destination_path)
|
||||
pub.publish(enable_exit_status=enable_exit_status)
|
||||
|
||||
return pub.writer.parts['body'], pub.document.reporter.max_level, pub.settings.record_dependencies
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
[Core]
|
||||
Name = upgrade_metadata
|
||||
Module = upgrade_metadata
|
||||
|
||||
[Nikola]
|
||||
MinVersion = 7.4.0
|
||||
|
||||
[Documentation]
|
||||
Author = Chris Warrick
|
||||
Version = 0.1.3
|
||||
Website = http://plugins.getnikola.com/#upgrade_metadata
|
||||
Description = Upgrade old-style metadata
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright © 2014–2015, Chris Warrick.
|
||||
|
||||
# Permission is hereby granted, free of charge, to any
|
||||
# person obtaining a copy of this software and associated
|
||||
# documentation files (the "Software"), to deal in the
|
||||
# Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the
|
||||
# Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice
|
||||
# shall be included in all copies or substantial portions of
|
||||
# the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import io
|
||||
import os
|
||||
import nikola.post
|
||||
from nikola.plugin_categories import Command
|
||||
from nikola import utils
|
||||
|
||||
|
||||
class UpgradeMetadata(Command):
|
||||
"""Upgrade metadata from the old no-descriptions format to the new reST-esque format."""
|
||||
|
||||
name = 'upgrade_metadata'
|
||||
doc_purpose = 'upgrade old-style metadata'
|
||||
cmd_options = [
|
||||
{
|
||||
'name': 'yes',
|
||||
'short': 'y',
|
||||
'long': 'yes',
|
||||
'type': bool,
|
||||
'default': False,
|
||||
'help': 'Proceed without confirmation',
|
||||
},
|
||||
]
|
||||
fields = ('title', 'slug', 'date', 'tags', 'link', 'description', 'type')
|
||||
|
||||
def _execute(self, options, args):
|
||||
L = utils.get_logger('upgrade_metadata', self.site.loghandlers)
|
||||
nikola.post._UPGRADE_METADATA_ADVERTISED = True
|
||||
|
||||
# scan posts
|
||||
self.site.scan_posts()
|
||||
flagged = []
|
||||
for post in self.site.timeline:
|
||||
if not post.newstylemeta:
|
||||
flagged.append(post)
|
||||
if flagged:
|
||||
if len(flagged) == 1:
|
||||
L.info('1 post (and/or its translations) contains old-style metadata:')
|
||||
else:
|
||||
L.info('{0} posts (and/or their translations) contain old-style metadata:'.format(len(flagged)))
|
||||
for post in flagged:
|
||||
L.info(' ' + post.metadata_path)
|
||||
if not options['yes']:
|
||||
yesno = utils.ask_yesno("Proceed with metadata upgrade?")
|
||||
if options['yes'] or yesno:
|
||||
for post in flagged:
|
||||
for lang in self.site.config['TRANSLATIONS'].keys():
|
||||
if lang == post.default_lang:
|
||||
fname = post.metadata_path
|
||||
else:
|
||||
meta_path = os.path.splitext(post.source_path)[0] + '.meta'
|
||||
fname = utils.get_translation_candidate(post.config, meta_path, lang)
|
||||
|
||||
if os.path.exists(fname):
|
||||
with io.open(fname, 'r', encoding='utf-8') as fh:
|
||||
meta = fh.readlines()
|
||||
|
||||
if not meta[min(1, len(meta) - 1)].startswith('.. '):
|
||||
# check if we’re dealing with old style metadata
|
||||
with io.open(fname, 'w', encoding='utf-8') as fh:
|
||||
for k, v in zip(self.fields, meta):
|
||||
fh.write('.. {0}: {1}'.format(k, v))
|
||||
L.debug(fname)
|
||||
|
||||
L.info('{0} posts upgraded.'.format(len(flagged)))
|
||||
else:
|
||||
L.info('Metadata not upgraded.')
|
||||
else:
|
||||
L.info('No old-style metadata posts found. No action is required.')
|
||||
16
posts/2016/12/happy-christmas.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<!--
|
||||
.. title: Happy Christmas
|
||||
.. slug: happy-christmas
|
||||
.. date: 2016-12-29 07:31:44 UTC-06:00
|
||||
.. tags:
|
||||
.. category:
|
||||
.. link:
|
||||
.. description:
|
||||
.. type: text
|
||||
-->
|
||||
|
||||
*Note- This is late due to software breakage*
|
||||
|
||||
Just a quick note before the end of the year to wish everyone a happy Christmas, holidays, and/or New Year!
|
||||
|
||||

|
||||
20
posts/2017/01/happy-new-year.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<!--
|
||||
.. title: Happy New Year
|
||||
.. slug: happy-new-year
|
||||
.. date: 2017-01-01 22:26:50 UTC-06:00
|
||||
.. tags:
|
||||
.. category:
|
||||
.. link:
|
||||
.. description:
|
||||
.. type: text
|
||||
-->
|
||||
|
||||
Hello, and welcome to the new year! If you are reading this, then you are one of the lucky ones who made it through 2016. We lost a lot of important and highly entertaining folks in 2016.
|
||||
|
||||
Since this is a new year, I have decided that I should try those silly resolution things again. My two big ones I am willing to go public with are to get into better shape and the other is to complete another Project 365. So far, I am 100% on the second goal!
|
||||
|
||||
You should go look at[p365.donaldharper.com](http://p365.donaldharper.com) and keep me honest.
|
||||
|
||||
As for the getting fit thing, I cheated, and started a couple of weeks ago. My two short term goals are to get to the point where I can do 100 push-ups daily (I am already up to 55 from starting at 10), and to be up and moving for at least 60 minutes daily. I have been tracking the movement for a while, and I am hit an miss. It is always harder over the holidays, but I think I can easily get that one going well.
|
||||
|
||||
See you in a while!
|
||||
BIN
sigal/pictures/Lego/20160124213756.jpg
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
sigal/pictures/Lego/20160124213819.jpg
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
sigal/pictures/Lego/20160823082723.jpg
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
sigal/pictures/Lego/20160928165449.jpg
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
sigal/pictures/Lego/20161220102042.jpg
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
sigal/pictures/Lego/20161220102118.jpg
Normal file
|
After Width: | Height: | Size: 881 KiB |
BIN
sigal/pictures/Lego/20161220102349.jpg
Normal file
|
After Width: | Height: | Size: 961 KiB |
BIN
sigal/pictures/Lego/20161220102414.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
sigal/pictures/Lego/20161220102519.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |