Change the output directory structure and a bit the templates structure as well.
--HG-- rename : pelican/themes/martyalchin/css/style.css => pelican/themes/martyalchin/static/css/style.css rename : pelican/themes/notmyidea/css/main.css => pelican/themes/notmyidea/static/css/main.css rename : pelican/themes/notmyidea/css/pygment.css => pelican/themes/notmyidea/static/css/pygment.css rename : pelican/themes/notmyidea/css/reset.css => pelican/themes/notmyidea/static/css/reset.css rename : pelican/themes/notmyidea/css/wide.css => pelican/themes/notmyidea/static/css/wide.css rename : pelican/themes/notmyidea/images/icons/delicious.png => pelican/themes/notmyidea/static/images/icons/delicious.png rename : pelican/themes/notmyidea/images/icons/lastfm.png => pelican/themes/notmyidea/static/images/icons/lastfm.png rename : pelican/themes/notmyidea/images/icons/linkedin.png => pelican/themes/notmyidea/static/images/icons/linkedin.png rename : pelican/themes/notmyidea/images/icons/rss.png => pelican/themes/notmyidea/static/images/icons/rss.png rename : pelican/themes/notmyidea/images/icons/twitter.png => pelican/themes/notmyidea/static/images/icons/twitter.png
2
TODO
|
|
@ -1,8 +1,6 @@
|
||||||
* Add a way to support pictures (see how sphinx makes that)
|
* Add a way to support pictures (see how sphinx makes that)
|
||||||
* Find a way to extend the existing templates instead of rewriting all from scratch.
|
* Find a way to extend the existing templates instead of rewriting all from scratch.
|
||||||
* find a better way to specify the templates. an idea is simply to install the templates in a default path, and to add a way to specify them by default under a "_themes" dir.
|
|
||||||
* Make the program support UTF8-encoded files as input (and later: any encoding?)
|
* Make the program support UTF8-encoded files as input (and later: any encoding?)
|
||||||
* Change the directory structure ?
|
|
||||||
* Add status support (draft, published, hidden)
|
* Add status support (draft, published, hidden)
|
||||||
* Add a serve + automatic generation behaviour.
|
* Add a serve + automatic generation behaviour.
|
||||||
* Recompile only the changed files, not all.
|
* Recompile only the changed files, not all.
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ _TEMPLATES = ('index', 'tag', 'tags', 'article', 'category', 'categories',
|
||||||
class Generator(object):
|
class Generator(object):
|
||||||
"""Handle all generation process: files writes, feed creation, and this
|
"""Handle all generation process: files writes, feed creation, and this
|
||||||
kind of basic stuff"""
|
kind of basic stuff"""
|
||||||
|
|
||||||
def __init__(self, settings=None, path=None, theme=None, output_path=None,
|
def __init__(self, settings=None, path=None, theme=None, output_path=None,
|
||||||
markup=None):
|
markup=None):
|
||||||
"""Read the settings, and performs some checks on the environement
|
"""Read the settings, and performs some checks on the environment
|
||||||
before doing anything else.
|
before doing anything else.
|
||||||
"""
|
"""
|
||||||
if settings is None:
|
if settings is None:
|
||||||
|
|
@ -64,7 +64,7 @@ class Generator(object):
|
||||||
for p in processors:
|
for p in processors:
|
||||||
p.process(context, self)
|
p.process(context, self)
|
||||||
|
|
||||||
def generate_feed(self, elements, context, filename=None,
|
def generate_feed(self, elements, context, filename=None,
|
||||||
relative_urls=True):
|
relative_urls=True):
|
||||||
"""Generate a feed with the list of articles provided
|
"""Generate a feed with the list of articles provided
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ class Generator(object):
|
||||||
the feed object.
|
the feed object.
|
||||||
|
|
||||||
:param articles: the articles to put on the feed.
|
:param articles: the articles to put on the feed.
|
||||||
:param context: the context to get the feed metadatas.
|
:param context: the context to get the feed metadata.
|
||||||
:param output_path: where to output the file.
|
:param output_path: where to output the file.
|
||||||
:param filename: the filename to output.
|
:param filename: the filename to output.
|
||||||
:param relative_urls: use relative urls or absolutes ones
|
:param relative_urls: use relative urls or absolutes ones
|
||||||
|
|
@ -104,11 +104,11 @@ class Generator(object):
|
||||||
fp = open(complete_path, 'w')
|
fp = open(complete_path, 'w')
|
||||||
feed.write(fp, 'utf-8')
|
feed.write(fp, 'utf-8')
|
||||||
print u' [ok] writing %s' % complete_path
|
print u' [ok] writing %s' % complete_path
|
||||||
|
|
||||||
fp.close()
|
fp.close()
|
||||||
return feed
|
return feed
|
||||||
|
|
||||||
def generate_file(self, name, template, context, relative_urls=True,
|
def generate_file(self, name, template, context, relative_urls=True,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
"""Write the file with the given informations
|
"""Write the file with the given informations
|
||||||
|
|
||||||
|
|
@ -166,7 +166,7 @@ class Generator(object):
|
||||||
files.extend([os.sep.join((root, f)) for f in temp_files
|
files.extend([os.sep.join((root, f)) for f in temp_files
|
||||||
if True in [f.endswith(ext) for ext in extensions]])
|
if True in [f.endswith(ext) for ext in extensions]])
|
||||||
return files
|
return files
|
||||||
|
|
||||||
def _get_relative_siteurl(self, filename):
|
def _get_relative_siteurl(self, filename):
|
||||||
"""Return the siteurl relative to the given filename"""
|
"""Return the siteurl relative to the given filename"""
|
||||||
return '../' * filename.count('/') + '.'
|
return '../' * filename.count('/') + '.'
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ _DIRECT_TEMPLATES = ('index', 'tags', 'categories', 'archives')
|
||||||
class Processor(object):
|
class Processor(object):
|
||||||
|
|
||||||
def _update_context(self, context, items):
|
def _update_context(self, context, items):
|
||||||
"""Update the context with the given items from the currrent
|
"""Update the context with the given items from the currrent
|
||||||
processor.
|
processor.
|
||||||
"""
|
"""
|
||||||
for item in items:
|
for item in items:
|
||||||
|
|
@ -24,20 +24,20 @@ class Processor(object):
|
||||||
class ArticlesProcessor(Processor):
|
class ArticlesProcessor(Processor):
|
||||||
|
|
||||||
def __init__(self, settings=None):
|
def __init__(self, settings=None):
|
||||||
self.articles = []
|
self.articles = []
|
||||||
self.dates = {}
|
self.dates = {}
|
||||||
self.years = {}
|
self.years = {}
|
||||||
self.tags = {}
|
self.tags = {}
|
||||||
self.categories = {}
|
self.categories = {}
|
||||||
|
|
||||||
def generate_feeds(self, context, generator):
|
def generate_feeds(self, context, generator):
|
||||||
"""Generate the feeds from the current context, and output files."""
|
"""Generate the feeds from the current context, and output files."""
|
||||||
|
|
||||||
generator.generate_feed(self.articles, context, context['FEED'])
|
generator.generate_feed(self.articles, context, context['FEED'])
|
||||||
|
|
||||||
for cat, arts in self.categories.items():
|
for cat, arts in self.categories.items():
|
||||||
arts.sort(key=attrgetter('date'), reverse=True)
|
arts.sort(key=attrgetter('date'), reverse=True)
|
||||||
generator.generate_feed(arts, context,
|
generator.generate_feed(arts, context,
|
||||||
context['CATEGORY_FEED'] % cat)
|
context['CATEGORY_FEED'] % cat)
|
||||||
|
|
||||||
def generate_pages(self, context, generator):
|
def generate_pages(self, context, generator):
|
||||||
|
|
@ -92,7 +92,7 @@ class ArticlesProcessor(Processor):
|
||||||
# sort the articles by date
|
# sort the articles by date
|
||||||
self.articles.sort(key=attrgetter('date'), reverse=True)
|
self.articles.sort(key=attrgetter('date'), reverse=True)
|
||||||
# and generate the output :)
|
# and generate the output :)
|
||||||
self._update_context(context, ('articles', 'dates', 'years',
|
self._update_context(context, ('articles', 'dates', 'years',
|
||||||
'tags', 'categories'))
|
'tags', 'categories'))
|
||||||
|
|
||||||
def process(self, context, generator):
|
def process(self, context, generator):
|
||||||
|
|
@ -116,11 +116,11 @@ class PagesProcessor(Processor):
|
||||||
self.pages.append(page)
|
self.pages.append(page)
|
||||||
|
|
||||||
context['PAGES'] = self.pages
|
context['PAGES'] = self.pages
|
||||||
|
|
||||||
def process(self, context, generator):
|
def process(self, context, generator):
|
||||||
templates = generator.get_templates()
|
templates = generator.get_templates()
|
||||||
for page in self.pages:
|
for page in self.pages:
|
||||||
generator.generate_file('pages/%s' % page.url,
|
generator.generate_file('pages/%s' % page.url,
|
||||||
templates['page'], context, page=page)
|
templates['page'], context, page=page)
|
||||||
self._update_context(context, ('pages',))
|
self._update_context(context, ('pages',))
|
||||||
|
|
||||||
|
|
@ -128,10 +128,17 @@ class PagesProcessor(Processor):
|
||||||
class StaticProcessor(Processor):
|
class StaticProcessor(Processor):
|
||||||
"""copy static paths to output"""
|
"""copy static paths to output"""
|
||||||
|
|
||||||
|
def _copy_paths(self, paths, source, destination, output_path,
|
||||||
|
final_path=None):
|
||||||
|
for path in paths:
|
||||||
|
copytree(path, source, os.path.join(output_path, destination),
|
||||||
|
final_path)
|
||||||
|
|
||||||
def process(self, context, generator):
|
def process(self, context, generator):
|
||||||
for path in generator.settings['STATIC_PATHS']:
|
self._copy_paths(generator.settings['STATIC_PATHS'], generator.path,
|
||||||
copytree(path, generator.theme, generator.output_path)
|
'static', generator.output_path)
|
||||||
copytree('pics', generator.path, generator.output_path)
|
self._copy_paths(generator.settings['THEME_PATHS'], generator.theme,
|
||||||
|
'theme', generator.output_path, '.')
|
||||||
|
|
||||||
|
|
||||||
class PdfProcessor(Processor):
|
class PdfProcessor(Processor):
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ _DEFAULT_CONFIG = {'PATH': None,
|
||||||
'THEME': _DEFAULT_THEME,
|
'THEME': _DEFAULT_THEME,
|
||||||
'OUTPUT_PATH': 'output/',
|
'OUTPUT_PATH': 'output/',
|
||||||
'MARKUP': ('rst', 'md'),
|
'MARKUP': ('rst', 'md'),
|
||||||
'STATIC_PATHS': ['css', 'images'],
|
'STATIC_PATHS': ['images',],
|
||||||
|
'THEME_PATHS': ['static',],
|
||||||
'FEED': 'feeds/all.atom.xml',
|
'FEED': 'feeds/all.atom.xml',
|
||||||
'CATEGORY_FEED': 'feeds/%s.atom.xml',
|
'CATEGORY_FEED': 'feeds/%s.atom.xml',
|
||||||
'SITENAME': 'A Pelican Blog',
|
'SITENAME': 'A Pelican Blog',
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<title>{% block title %}{{ SITENAME }}{%endblock%}</title>
|
<title>{% block title %}{{ SITENAME }}{%endblock%}</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="stylesheet" href="{{ SITEURL }}/css/style.css" type="text/css" />
|
<link rel="stylesheet" href="{{ SITEURL }}/theme/css/style.css" type="text/css" />
|
||||||
<link href="{{ SITEURL }}/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} ATOM Feed" />
|
<link href="{{ SITEURL }}/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} ATOM Feed" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 963 B After Width: | Height: | Size: 963 B |
|
Before Width: | Height: | Size: 980 B After Width: | Height: | Size: 980 B |
|
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 376 B |
|
Before Width: | Height: | Size: 896 B After Width: | Height: | Size: 896 B |
|
Before Width: | Height: | Size: 835 B After Width: | Height: | Size: 835 B |
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<title>{% block title %}{{ SITENAME }}{%endblock%}</title>
|
<title>{% block title %}{{ SITENAME }}{%endblock%}</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="stylesheet" href="{{ SITEURL }}/css/{{ CSS_FILE }}" type="text/css" />
|
<link rel="stylesheet" href="{{ SITEURL }}/theme/css/{{ CSS_FILE }}" type="text/css" />
|
||||||
<link href="{{ SITEURL }}/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} ATOM Feed" />
|
<link href="{{ SITEURL }}/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} ATOM Feed" />
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,14 +50,16 @@ def slugify(value):
|
||||||
value = unicode(re.sub('[^\w\s-]', '', value).strip().lower())
|
value = unicode(re.sub('[^\w\s-]', '', value).strip().lower())
|
||||||
return re.sub('[-\s]+', '-', value)
|
return re.sub('[-\s]+', '-', value)
|
||||||
|
|
||||||
def copytree(path, origin, destination):
|
def copytree(path, origin, destination, topath=None):
|
||||||
"""Copy path from origin to destination, silent any errors"""
|
"""Copy path from origin to destination, silent any errors"""
|
||||||
|
|
||||||
|
if not topath:
|
||||||
|
topath = path
|
||||||
try:
|
try:
|
||||||
fromp = os.path.expanduser(os.path.join(origin, path))
|
fromp = os.path.expanduser(os.path.join(origin, path))
|
||||||
to = os.path.expanduser(os.path.join(destination, path))
|
to = os.path.expanduser(os.path.join(destination, topath))
|
||||||
shutil.copytree(fromp, to)
|
shutil.copytree(fromp, to)
|
||||||
print u' [ok] copying %s' % fromp
|
print u' [ok] copying %s to %s' % (fromp, to)
|
||||||
|
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||