initial commit to seperate repo
This commit is contained in:
commit
1a020ca68b
1302 changed files with 201261 additions and 0 deletions
1
plugins/__init__ (restored).py
Normal file
1
plugins/__init__ (restored).py
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Plugin modules go here.
|
||||
1
plugins/__init__.py
Normal file
1
plugins/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Plugin modules go here.
|
||||
9
plugins/import_feed/README.md
Normal file
9
plugins/import_feed/README.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
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 feed_url
|
||||
```
|
||||
|
||||
BIN
plugins/import_feed/__pycache__/import_feed.cpython-34.pyc
Normal file
BIN
plugins/import_feed/__pycache__/import_feed.cpython-34.pyc
Normal file
Binary file not shown.
10
plugins/import_feed/import_feed.plugin
Normal file
10
plugins/import_feed/import_feed.plugin
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[Core]
|
||||
Name = import_feed
|
||||
Module = import_feed
|
||||
|
||||
[Documentation]
|
||||
Author = Grzegorz Śliwiński
|
||||
Version = 0.1
|
||||
Website = http://www.fizyk.net.pl/
|
||||
Description = Import a blog posts from a RSS/Atom dump
|
||||
|
||||
200
plugins/import_feed/import_feed.py
Normal file
200
plugins/import_feed/import_feed.py
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
# -*- 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] feed_file"
|
||||
doc_purpose = "import a RSS/Atom dump"
|
||||
cmd_options = ImportMixin.cmd_options
|
||||
|
||||
def _execute(self, options, args):
|
||||
'''
|
||||
Import Atom/RSS feed
|
||||
'''
|
||||
if feedparser is None:
|
||||
req_missing(['feedparser'], 'import feeds')
|
||||
return
|
||||
|
||||
if not args:
|
||||
print(self.help())
|
||||
return
|
||||
|
||||
options['filename'] = args[0]
|
||||
self.feed_export_file = options['filename']
|
||||
self.output_folder = options['output_folder']
|
||||
self.import_into_existing_site = False
|
||||
self.url_map = {}
|
||||
channel = self.get_channel_from_file(self.feed_export_file)
|
||||
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')
|
||||
|
||||
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)
|
||||
BIN
plugins/import_feed/import_feed.pyc
Normal file
BIN
plugins/import_feed/import_feed.pyc
Normal file
Binary file not shown.
1
plugins/import_feed/requiremets.txt
Normal file
1
plugins/import_feed/requiremets.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
feedparser
|
||||
8
plugins/less/README.md
Normal file
8
plugins/less/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Compile [LESS](http://lesscss.org/) source files into CSS.
|
||||
|
||||
To use this plugin:
|
||||
|
||||
Create a ``less`` folder in your theme, put your ``.less`` files there, add a ``less/targets`` file listing the files you
|
||||
want compiled.
|
||||
|
||||
|
||||
BIN
plugins/less/__pycache__/less.cpython-34.pyc
Normal file
BIN
plugins/less/__pycache__/less.cpython-34.pyc
Normal file
Binary file not shown.
10
plugins/less/less.plugin
Normal file
10
plugins/less/less.plugin
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[Core]
|
||||
Name = less
|
||||
Module = less
|
||||
|
||||
[Documentation]
|
||||
Author = Roberto Alsina
|
||||
Version = 0.1
|
||||
Website = http://plugins.getnikola.com/#less
|
||||
Description = Build CSS out of LESS sources
|
||||
|
||||
121
plugins/less/less.py
Normal file
121
plugins/less/less.py
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# -*- 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
|
||||
|
||||
import codecs
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from nikola.plugin_categories import Task
|
||||
from nikola import utils
|
||||
|
||||
|
||||
class BuildLess(Task):
|
||||
"""Generate CSS out of LESS sources."""
|
||||
|
||||
name = "build_less"
|
||||
sources_folder = "less"
|
||||
sources_ext = ".less"
|
||||
|
||||
def gen_tasks(self):
|
||||
"""Generate CSS out of LESS sources."""
|
||||
self.compiler_name = self.site.config['LESS_COMPILER']
|
||||
self.compiler_options = self.site.config['LESS_OPTIONS']
|
||||
|
||||
kw = {
|
||||
'cache_folder': self.site.config['CACHE_FOLDER'],
|
||||
'themes': self.site.THEMES,
|
||||
}
|
||||
tasks = {}
|
||||
|
||||
# Find where in the theme chain we define the LESS targets
|
||||
# There can be many *.less in the folder, but we only will build
|
||||
# the ones listed in less/targets
|
||||
if os.path.isfile(os.path.join(self.sources_folder, "targets")):
|
||||
targets_path = os.path.join(self.sources_folder, "targets")
|
||||
else:
|
||||
targets_path = utils.get_asset_path(os.path.join(self.sources_folder, "targets"), self.site.THEMES)
|
||||
try:
|
||||
with codecs.open(targets_path, "rb", "utf-8") as inf:
|
||||
targets = [x.strip() for x in inf.readlines()]
|
||||
except Exception:
|
||||
targets = []
|
||||
|
||||
for task in utils.copy_tree(self.sources_folder, os.path.join(kw['cache_folder'], self.sources_folder)):
|
||||
if task['name'] in tasks:
|
||||
continue
|
||||
task['basename'] = 'prepare_less_sources'
|
||||
tasks[task['name']] = task
|
||||
yield task
|
||||
|
||||
for theme_name in kw['themes']:
|
||||
src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder)
|
||||
for task in utils.copy_tree(src, os.path.join(kw['cache_folder'], self.sources_folder)):
|
||||
task['basename'] = 'prepare_less_sources'
|
||||
yield task
|
||||
|
||||
# Build targets and write CSS files
|
||||
base_path = utils.get_theme_path(self.site.THEMES[0])
|
||||
dst_dir = os.path.join(self.site.config['OUTPUT_FOLDER'], 'assets', 'css')
|
||||
# Make everything depend on all sources, rough but enough
|
||||
deps = []
|
||||
if os.path.isfile(os.path.join(self.sources_folder, "targets")):
|
||||
deps += glob.glob(os.path.join(kw['cache_folder'], self.sources_folder,
|
||||
'*{0}'.format(self.sources_ext)))
|
||||
else:
|
||||
deps += glob.glob(os.path.join(base_path, self.sources_folder,
|
||||
'*{0}'.format(self.sources_ext)))
|
||||
|
||||
def compile_target(target, dst):
|
||||
utils.makedirs(dst_dir)
|
||||
src = os.path.join(kw['cache_folder'], self.sources_folder, target)
|
||||
run_in_shell = sys.platform == 'win32'
|
||||
try:
|
||||
compiled = subprocess.check_output([self.compiler_name] + self.compiler_options + [src], shell=run_in_shell)
|
||||
except OSError:
|
||||
utils.req_missing([self.compiler_name],
|
||||
'build LESS files (and use this theme)',
|
||||
False, False)
|
||||
with open(dst, "wb+") as outf:
|
||||
outf.write(compiled)
|
||||
|
||||
yield self.group_task()
|
||||
|
||||
for target in targets:
|
||||
dst = os.path.join(dst_dir, target.replace(self.sources_ext, ".css"))
|
||||
yield {
|
||||
'basename': self.name,
|
||||
'name': dst,
|
||||
'targets': [dst],
|
||||
'file_dep': deps,
|
||||
'task_dep': ['prepare_less_sources'],
|
||||
'actions': ((compile_target, [target, dst]), ),
|
||||
'uptodate': [utils.config_changed(kw)],
|
||||
'clean': True
|
||||
}
|
||||
BIN
plugins/less/less.pyc
Normal file
BIN
plugins/less/less.pyc
Normal file
Binary file not shown.
1
plugins/less/requirements-nonpy.txt
Normal file
1
plugins/less/requirements-nonpy.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
LESS::http://lesscss.org
|
||||
8
plugins/sass/README.md
Normal file
8
plugins/sass/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Compile [SASS](http://sass-lang.com/) source files into CSS.
|
||||
|
||||
To use this plugin:
|
||||
|
||||
Create a ``sass`` folder in your theme, put your ``.scss`` files there, add a ``sass/targets`` file listing the files you
|
||||
want compiled.
|
||||
|
||||
|
||||
BIN
plugins/sass/__pycache__/sass.cpython-34.pyc
Normal file
BIN
plugins/sass/__pycache__/sass.cpython-34.pyc
Normal file
Binary file not shown.
1
plugins/sass/requirements-nonpy.txt
Normal file
1
plugins/sass/requirements-nonpy.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
SASS::http://sass-lang.com
|
||||
9
plugins/sass/sass.plugin
Normal file
9
plugins/sass/sass.plugin
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[Core]
|
||||
Name = sass
|
||||
Module = sass
|
||||
|
||||
[Documentation]
|
||||
Author = Roberto Alsina, Chris "Kwpolska" Warrick
|
||||
Version = 0.1
|
||||
Website = http://plugins.getnikola.com/#sass
|
||||
Description = Build CSS out of Sass sources
|
||||
143
plugins/sass/sass.py
Normal file
143
plugins/sass/sass.py
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
# -*- 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
|
||||
|
||||
import codecs
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from nikola.plugin_categories import Task
|
||||
from nikola import utils
|
||||
|
||||
|
||||
class BuildSass(Task):
|
||||
"""Generate CSS out of Sass sources."""
|
||||
|
||||
name = "build_sass"
|
||||
sources_folder = "sass"
|
||||
sources_ext = (".sass", ".scss")
|
||||
|
||||
def gen_tasks(self):
|
||||
"""Generate CSS out of Sass sources."""
|
||||
self.logger = utils.get_logger('build_sass', self.site.loghandlers)
|
||||
self.compiler_name = self.site.config['SASS_COMPILER']
|
||||
self.compiler_options = self.site.config['SASS_OPTIONS']
|
||||
|
||||
kw = {
|
||||
'cache_folder': self.site.config['CACHE_FOLDER'],
|
||||
'themes': self.site.THEMES,
|
||||
}
|
||||
tasks = {}
|
||||
|
||||
# Find where in the theme chain we define the Sass targets
|
||||
# There can be many *.sass/*.scss in the folder, but we only
|
||||
# will build the ones listed in sass/targets
|
||||
if os.path.isfile(os.path.join(self.sources_folder, "targets")):
|
||||
targets_path = os.path.join(self.sources_folder, "targets")
|
||||
else:
|
||||
targets_path = utils.get_asset_path(os.path.join(self.sources_folder, "targets"), self.site.THEMES)
|
||||
try:
|
||||
with codecs.open(targets_path, "rb", "utf-8") as inf:
|
||||
targets = [x.strip() for x in inf.readlines()]
|
||||
except Exception:
|
||||
targets = []
|
||||
|
||||
for task in utils.copy_tree(self.sources_folder, os.path.join(kw['cache_folder'], self.sources_folder)):
|
||||
if task['name'] in tasks:
|
||||
continue
|
||||
task['basename'] = 'prepare_sass_sources'
|
||||
tasks[task['name']] = task
|
||||
yield task
|
||||
|
||||
for theme_name in kw['themes']:
|
||||
src = os.path.join(utils.get_theme_path(theme_name), self.sources_folder)
|
||||
for task in utils.copy_tree(src, os.path.join(kw['cache_folder'], self.sources_folder)):
|
||||
if task['name'] in tasks:
|
||||
continue
|
||||
task['basename'] = 'prepare_sass_sources'
|
||||
tasks[task['name']] = task
|
||||
yield task
|
||||
|
||||
# Build targets and write CSS files
|
||||
base_path = utils.get_theme_path(self.site.THEMES[0])
|
||||
dst_dir = os.path.join(self.site.config['OUTPUT_FOLDER'], 'assets', 'css')
|
||||
# Make everything depend on all sources, rough but enough
|
||||
deps = []
|
||||
for ext in self.sources_ext:
|
||||
if os.path.isfile(os.path.join(self.sources_folder, "targets")):
|
||||
deps += glob.glob(os.path.join(kw['cache_folder'], self.sources_folder,
|
||||
'*{0}'.format(ext)))
|
||||
else:
|
||||
deps += glob.glob(os.path.join(base_path, self.sources_folder,
|
||||
'*{0}'.format(ext)))
|
||||
|
||||
def compile_target(target, dst):
|
||||
utils.makedirs(dst_dir)
|
||||
run_in_shell = sys.platform == 'win32'
|
||||
src = os.path.join(kw['cache_folder'], self.sources_folder, target)
|
||||
try:
|
||||
compiled = subprocess.check_output([self.compiler_name] + self.compiler_options + [src], shell=run_in_shell)
|
||||
except OSError:
|
||||
utils.req_missing([self.compiler_name],
|
||||
'build Sass files (and use this theme)',
|
||||
False, False)
|
||||
with open(dst, "wb+") as outf:
|
||||
outf.write(compiled)
|
||||
|
||||
yield self.group_task()
|
||||
|
||||
# We can have file conflicts. This is a way to prevent them.
|
||||
# I orignally wanted to use sets and their cannot-have-duplicates
|
||||
# magic, but I decided not to do this so we can show the user
|
||||
# what files were problematic.
|
||||
# If we didn’t do this, there would be a cryptic message from doit
|
||||
# instead.
|
||||
seennames = {}
|
||||
for target in targets:
|
||||
base = os.path.splitext(target)[0]
|
||||
dst = os.path.join(dst_dir, base + ".css")
|
||||
|
||||
if base in seennames:
|
||||
self.logger.error(
|
||||
'Duplicate filenames for Sass compiled files: {0} and '
|
||||
'{1} (both compile to {2})'.format(
|
||||
seennames[base], target, base + ".css"))
|
||||
else:
|
||||
seennames.update({base: target})
|
||||
|
||||
yield {
|
||||
'basename': self.name,
|
||||
'name': dst,
|
||||
'targets': [dst],
|
||||
'file_dep': deps,
|
||||
'task_dep': ['prepare_sass_sources'],
|
||||
'actions': ((compile_target, [target, dst]), ),
|
||||
'uptodate': [utils.config_changed(kw)],
|
||||
'clean': True
|
||||
}
|
||||
BIN
plugins/sass/sass.pyc
Normal file
BIN
plugins/sass/sass.pyc
Normal file
Binary file not shown.
Binary file not shown.
12
plugins/upgrade_metadata/upgrade_metadata.plugin
Normal file
12
plugins/upgrade_metadata/upgrade_metadata.plugin
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[Core]
|
||||
Name = upgrade_metadata
|
||||
Module = upgrade_metadata
|
||||
|
||||
[Nikola]
|
||||
MinVersion = 7.4.0
|
||||
|
||||
[Documentation]
|
||||
Author = Chris Warrick
|
||||
Version = 0.1.2
|
||||
Website = http://plugins.getnikola.com/#upgrade_metadata
|
||||
Description = Upgrade old-style metadata
|
||||
94
plugins/upgrade_metadata/upgrade_metadata.py
Normal file
94
plugins/upgrade_metadata/upgrade_metadata.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# -*- 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 post.translated_to:
|
||||
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)
|
||||
|
||||
with io.open(fname, 'r', encoding='utf-8') as fh:
|
||||
meta = fh.readlines()
|
||||
|
||||
if not 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.')
|
||||
40
plugins/vcs/README.md
Normal file
40
plugins/vcs/README.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
This **EXPERIMENTAL** plugin tries to make it easy to keep your site in a version control system.
|
||||
|
||||
**REMEMBER**, this is a first iteration, it's probably buggy, so be careful, and only use it
|
||||
if you are experienced with your VCS, ok?
|
||||
|
||||
How to use it:
|
||||
|
||||
1. Choose your favourite VCS between git, bzr, subversion, mercurial.
|
||||
2. Initialize the repo in your site (for example: ``git init .``)
|
||||
3. Install this plugin: ``nikola plugin -i vcs``
|
||||
4. Run ``nikola vcs``
|
||||
5. Check what happened (for example: ``git status`` and ``git log``)
|
||||
6. Use your site as usual, creating posts, adding stuff or removing it
|
||||
7. GOTO 4.
|
||||
8. You may want to add ``nikola vcs`` to your deploy commands.
|
||||
|
||||
What it should do:
|
||||
|
||||
1. Add a lot of stuff to the repo:
|
||||
|
||||
* All your posts
|
||||
* All your pages
|
||||
* All your galleries' images
|
||||
* All your listings
|
||||
* All your static files
|
||||
* Your themes
|
||||
* Your plugins
|
||||
* Your conf.py
|
||||
|
||||
2. Remove stuff if you removed it
|
||||
3. Commit stuff if you changed it
|
||||
|
||||
What it should **NOT** do:
|
||||
|
||||
1. Lose your data
|
||||
2. Push it anywhere (yet)
|
||||
3. Manage your output (consider ``github_deploy`` would not like it!)
|
||||
|
||||
Please report anything missing, or any ideas on how to improve this, where you want this to go
|
||||
by [filing issues](https://github.com/getnikola/plugins/issues).
|
||||
BIN
plugins/vcs/__pycache__/vcs.cpython-34.pyc
Normal file
BIN
plugins/vcs/__pycache__/vcs.cpython-34.pyc
Normal file
Binary file not shown.
2
plugins/vcs/requirements.txt
Normal file
2
plugins/vcs/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
anyvc
|
||||
py
|
||||
9
plugins/vcs/vcs.plugin
Normal file
9
plugins/vcs/vcs.plugin
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[Core]
|
||||
Name = vcs
|
||||
Module = vcs
|
||||
|
||||
[Documentation]
|
||||
Author = Roberto Alsina
|
||||
Version = 1.0
|
||||
Website = https://getnikola.com
|
||||
Description = Site vcs
|
||||
114
plugins/vcs/vcs.py
Normal file
114
plugins/vcs/vcs.py
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright © 2015 Roberto Alsina.
|
||||
|
||||
# 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 print_function
|
||||
import os
|
||||
|
||||
from py.path import local
|
||||
from anyvc import workdir
|
||||
|
||||
from nikola.plugin_categories import Command
|
||||
from nikola.utils import get_logger
|
||||
|
||||
|
||||
def get_path_list(path):
|
||||
'''Walk path and return a list of everything in it.'''
|
||||
paths = []
|
||||
for root, dirs, files in os.walk(path, followlinks=True):
|
||||
for fname in files:
|
||||
fpath = os.path.join(root, fname)
|
||||
paths.append(fpath)
|
||||
return list(set(paths))
|
||||
|
||||
|
||||
class CommandVCS(Command):
|
||||
""" Site status. """
|
||||
name = "vcs"
|
||||
|
||||
doc_purpose = "display site status"
|
||||
doc_description = "Show information about the posts and site deployment."
|
||||
logger = None
|
||||
cmd_options = []
|
||||
|
||||
def _execute(self, options, args):
|
||||
logger = get_logger('vcs', self.site.loghandlers)
|
||||
self.site.scan_posts()
|
||||
|
||||
repo_path = local('.')
|
||||
wd = workdir.open(repo_path)
|
||||
|
||||
# See if anything got deleted
|
||||
del_paths = []
|
||||
flag = False
|
||||
for s in wd.status():
|
||||
if s.state == 'removed':
|
||||
if not flag:
|
||||
logger.info('Found deleted files')
|
||||
flag = True
|
||||
logger.info('DEL => {}', s.relpath)
|
||||
del_paths.append(s.relpath)
|
||||
|
||||
if flag:
|
||||
logger.info('Marking as deleted')
|
||||
wd.remove(paths=del_paths)
|
||||
wd.commit(message='Deleted Files', paths=del_paths)
|
||||
|
||||
# Collect all paths that should be kept under control
|
||||
# Post and page sources
|
||||
paths = []
|
||||
for lang in self.site.config['TRANSLATIONS']:
|
||||
for p in self.site.timeline:
|
||||
paths.extend(p.fragment_deps(lang))
|
||||
|
||||
# Files in general
|
||||
for k, v in self.site.config['FILES_FOLDERS'].items():
|
||||
paths.extend(get_path_list(k))
|
||||
for k, v in self.site.config['LISTINGS_FOLDERS'].items():
|
||||
paths.extend(get_path_list(k))
|
||||
for k, v in self.site.config['GALLERY_FOLDERS'].items():
|
||||
paths.extend(get_path_list(k))
|
||||
|
||||
# Themes and plugins
|
||||
for p in ['plugins', 'themes']:
|
||||
paths.extend(get_path_list(p))
|
||||
|
||||
# The configuration
|
||||
paths.extend('conf.py')
|
||||
|
||||
# Add them to the VCS
|
||||
paths = list(set(paths))
|
||||
wd.add(paths=paths)
|
||||
|
||||
flag = False
|
||||
for s in wd.status():
|
||||
if s.state == 'added':
|
||||
if not flag:
|
||||
logger.info('Found new files')
|
||||
flag = True
|
||||
logger.info('NEW => {}', s.relpath)
|
||||
|
||||
logger.info('Committing changes')
|
||||
wd.commit(message='Updated files')
|
||||
Loading…
Add table
Add a link
Reference in a new issue