Then edit ``weblog.ini`` and add the following lines::
html_header = html/header.html
extra_files = my_fancy_logo.png
This insert the content of the file ``html/header.html`` before the blog's
title, and copy the file ``my_fancy_logo.png``.
CSS resources
-------------
Learning and developing with CSS is hard. The CSS syntax tend to be confusing
for beginners. The numerous browser incompatibilities makes the designer's work
even more complicated. Here is a list of useful resources regarding this
subject:
* SitePoint_ CSS Reference is helpful if you are a beginner with CSS. It lists
all CSS properties and document how well they are supported by the different
browsers.
* HtmlHelp_ contains a complete HTML 4 reference.
.. _HtmlHelp: http://htmlhelp.com/reference/html40/
.. _SitePoint: http://reference.sitepoint.com/css
.. vim:se tw=80 sw=2 ts=2 et encoding=utf-8:
./weblog+jinja-1.0/doc/weblog.rst 0100644 0001750 0000000 00000025202 11060362513 0015670 0 ustar 00henry wheel Weblog manual
=============
:Author: Henry Prêcheur testpost!
© 2007 Me
Regenerate the blog files:: $ weblog publish Reload the page in your browser. You should see a second post with some formating. The default post file encoding is ASCII. To use a different encoding specify it via the field ``encoding``:: title: Encoding test date: 2007-11-5 encoding: latin-1 Here you can put some ISO-8856-1 text ... Specify the default encoding in ``weblog.ini``, to avoid setting the encoding field for every file. While writing your blog post, don't bother about the ``date`` field immediately. Weblog automatically sets the date to the filename's last modification time. A good practice though is to set the date when the post gets published. By doing so the date won't get changed if the file gets copied. To set the date of a post, use the command ``date``:: $ date Mon Apr 14 00:10:44 PDT 2008 $ cat my_blog_post.html title: My blog post This is a blog post without any date. $ weblog date my_blog_post.html Setting date to 2008-04-14 00:12:22 in file my_blog_post.html $ cat my_blog_post.html title: My blog post date: 2008-04-14 00:12:22 This is a blog post without any date. $ weblog date my_blog_post 2008-5-15 Setting date to 2008-05-15 in file my_blog_post.html $ cat my_blog_post.html title: My blog post date: 2008-05-15 This is a blog post without any date. The ``date`` command accepts 3 formats as argument: - YEAR-MONTH-DAY (2008-01-31) - YEAR-MONTH-DAY HOUR:MINUTE (2008-01-31 16:45) - YEAR-MONTH-DAY HOUR:MINUTE:SECONDS (2008-01-31 16:45:14) For conciseness the ``date`` command uses aliases to specify commonly used date: - now - today (like now but only set the date, not the time) - tomorrow (now + 24 hours) - next_day (like tomorrow but only sets the date, not the time) Encoding and escaping --------------------- Weblog tries to make sure its output is always *correct*. Non-ASCII characters, are converted to HTML entities so you don't have to worry about it. The output is *never* encoded into ISO-8856-1, UTF-8 or another non-ASCII encoding. Encoding conversions are not so simple in practice. By doing only one conversion to the simplest encoding possible, a lot of problems are solved. The content of the post is not escaped. The title and the date of the post are escaped. The title ``Hello World`` is escaped. HTML tags appear, and no formating is applied to ``world``. The original text "Hello World" appears instead of "Hello *World*", It is possible to override this by specifying ``raw`` as the encoding. Using the ``raw`` encoding nothing is escaped or converted, but you must make sure all characters are ASCII characters:: title: Non-escaped title author:Me<me@my_weblog.org> encoding: raw If the ``raw`` encoding is used, all the characters must be ASCII characters. Otherwise an error is reported. Attaching a file to a post -------------------------- To attach files like images to a blog post, use the field ``files``:: title: Attach a file files: picture.png directory/file
a file
It will copy ``picture.png`` and ``directory/file``. If ``directory`` does not exist,
it will be created.
How URI's are handled
---------------------
Relative links (````) are rewritten in the RSS file and in
some HTML files. In the RSS file ``base_url`` is prepended to the link to make
sure it always points to the correct URI.
Absolute links (````) are not rewritten. It should
always point to the correct location regardless of the context.
Note that Weblog considers ``/`` as the root directory. If ``base_url`` is
``http://example.com/``; ``test.html`` and ``/test.html`` are both rewritten to
``http://example.com/test.html``.
Command line parameters
-----------------------
Usage: weblog [options]
Options:
-h, --help show this help message and exit
-s DIR, --source-dir=DIR
The source directory where the blog posts and the file
weblog.ini are located
-o DIR, --output-dir=DIR
The directory where all the generated files are
written. If it does not exist it is created.
-q, --quiet Do not output anything except critical error messages
Configuration file
------------------
All configuration options are in the ``weblog`` section. Learn more about the
format of the configuration file:
http://docs.python.org/lib/module-ConfigParser.html.
A sample configuration file::
[weblog]
title: Blog's title
url: http://example.com/
description: A sample blog.
source_dir: path/to/my/posts
output_dir: path/to/output/directory
encoding: latin-1
author: Me testpost!
The author lastname is Prêcheur
./weblog+jinja-1.0/examples/enconding.html 0100644 0001750 0000000 00000000551 11060362513 0017562 0 ustar 00henry wheel title: Weblog encode le français! author: Henry Prêcheur
Weblog encode maintenant le texte correctement! Des caractéres tels que: È, Õ
ou Ä sont maintenant bien encodés!
Français, Español & Deutsh :)
The encoding of the file is ISO-8859-1 or latin-1.
./weblog+jinja-1.0/examples/first_post.html 0100644 0001750 0000000 00000000074 11060362513 0020012 0 ustar 00henry wheel title: First post author: Me date: 2007-08-25 Hello world! ./weblog+jinja-1.0/examples/w3_steely_style.css 0100644 0001750 0000000 00000000360 11060362513 0020576 0 ustar 00henry wheel body { text-align: center; /* for IE 4+ */ } div#main { margin: 0 auto; text-align: left; /* counter the body center */ width: 42em; max-width: 90%; } p.weblog-ad { margin: 0 auto; text-align: left !important; } ./weblog+jinja-1.0/examples/utf-8.html 0100644 0001750 0000000 00000000161 11060362513 0016556 0 ustar 00henry wheel title: Some UTF-8, ç ä é ö ó date: 2008-1-1 encoding: UTF-8 Test post with UTF-8 inside ... ç ä é ö ó ./weblog+jinja-1.0/examples/weblog.ini 0100644 0001750 0000000 00000000270 11060362513 0016706 0 ustar 00henry wheel [weblog] title=Sample blog url=http://blog.sample.org description=Brief description of this sample blog. Do multiline, this way! encoding=UTF-8 author=MePublished using Weblog
{% endif %} {% endblock %} {# vim:set ft=htmljinja: #} ./weblog+jinja-1.0/weblog/templates/index.html.tmpl 0100644 0001750 0000000 00000002105 11060362513 0021334 0 ustar 00henry wheel {% extends 'base.html.tmpl' %} {% block content %}{{ description|e }}
{% endif %} {% for post in post_list %}{{ post.date|format_date }},
{{ date|format_date }},
' becomes '
'
but
' is not changed since it is an
*absolute* URI.
>>> html_full_url('http://example.com', '')
""
>>> html_full_url('http://example.com', '
')
"
"
'''
p = FullUrlHtmlParser(base_url)
p.feed(text)
return p.buffer.getvalue()
if __name__ == '__main__':
import doctest
doctest.testmod()
./weblog+jinja-1.0/weblog/load.py 0100644 0001750 0000000 00000012757 11060362513 0015675 0 ustar 00henry wheel import os
import logging
from utils import encode, load_if_filename
from ConfigParser import SafeConfigParser
from post import Post
def load_configuration(configuration_file, source_dir=None):
'''
Read the file ``config_file`` and sanitise it. Returns a dictionnary
containing the parameters from the [weblog] section.
>>> from StringIO import StringIO
>>> config_file = StringIO("""[weblog]
... title = Test title
... url = http://example.com
... description = Example blog""")
>>> load_configuration(config_file) == {'url': 'http://example.com/',
... 'rss_limit': 10, 'description': 'Example blog',
... 'post_per_page': 10, 'title': 'Test title'}
True
The configuration file must have a `weblog` section containing at lease:
- `title`
- `url`
- `description`
>>> # Configuration without title
>>> config_file = StringIO("""[weblog]
... url = http://example.com
... description = example""")
>>> load_configuration(config_file)
Traceback (most recent call last):
...
KeyError: "Unable to find 'title' in configuration file 'unknown filename'"
>>> # Configuration without url
>>> config_file = StringIO("""[weblog]
... title = Example blog
... description = example""")
>>> load_configuration(config_file)
Traceback (most recent call last):
...
KeyError: "Unable to find 'url' in configuration file 'unknown filename'"
>>> # Configuration without description
>>> config_file = StringIO("""[weblog]
... title = Example blog
... url = http://example.com""")
>>> load_configuration(config_file)
Traceback (most recent call last):
...
KeyError: "Unable to find 'description' in configuration file 'unknown \
filename'"
Also some field must be integer:
- rss_limit
- post_per_page
>>> config_file = StringIO("""[weblog]
... title = Test title
... url = http://example.com
... description = Example blog
... rss_limit = not_a_number""")
>>> load_configuration(config_file)
Traceback (most recent call last):
...
ValueError: Error in configuration file 'unknown filename' 'rss_limit': \
invalid literal for int() with base 10: 'not_a_number'
>>> config_file = StringIO("""[weblog]
... title = Test title
... url = http://example.com
... description = Example blog
... post_per_page = not_a_number""")
>>> load_configuration(config_file)
Traceback (most recent call last):
...
ValueError: Error in configuration file 'unknown filename' \
'post_per_page': invalid literal for int() with base 10: 'not_a_number'
'''
config = SafeConfigParser()
if isinstance(configuration_file, basestring):
try:
f = file(configuration_file)
except IOError:
# The file was not found try to load it from the source directory if
# it is just a filename.
if os.path.basename(configuration_file) == configuration_file:
f = file(os.path.join(source_dir, configuration_file))
else:
raise
else:
f = configuration_file
configuration_file = 'unknown filename'
config.readfp(f)
config_dict = dict(config.items('weblog'))
try:
config_dict['title'] = encode(config_dict['title'],
config_dict.get('encoding', 'ascii'))
config_dict['description'] = encode(config_dict['description'],
config_dict.get('encoding',
'ascii'))
if not config_dict['url'].endswith('/'):
config_dict['url'] += '/'
def _load_if_filename(key):
if key in config_dict:
config_dict[key] = load_if_filename(source_dir,
config_dict[key])
_load_if_filename('html_head')
_load_if_filename('html_header')
_load_if_filename('html_footer')
def config_set_int(key, default):
try:
config_dict[key] = int(config_dict.get(key, default))
except ValueError, e:
raise ValueError('Error in configuration file \'%s\' \'%s\': %s'
% (configuration_file, key, e))
config_set_int('post_per_page', 10)
config_set_int('rss_limit', 10)
except KeyError, e:
raise KeyError('Unable to find %s in configuration file \'%s\'' %
(e, configuration_file))
else:
return config_dict
def load_post_list(path):
'''
List and load all the files ending with '.html' in the passed directory.
Returns a list containing ``Post`` objects created using the loaded files.
'''
post_list = set()
for filename in os.listdir(path):
if filename.endswith('.html'):
logging.debug('Loading \'%s\'', filename)
p = Post(os.path.join(path, filename))
if p in post_list:
logging.debug('%r is duplicated', p)
for duplicated_post in post_list:
if duplicated_post == p:
break
raise IOError('"%s", there is already a post '
'with this title and date ("%s")' % \
(filename, duplicated_post.get_filename()))
else:
post_list.add(p)
else:
logging.debug('Ignoring \'%s\'', filename)
return post_list
./weblog+jinja-1.0/weblog/post.py 0100644 0001750 0000000 00000021247 11060362513 0015735 0 ustar 00henry wheel import email
import codecs
import logging
from os import stat
from datetime import datetime, date
from urllib import quote
from cgi import escape
from utils import encode, escape_and_encode
class PostError(Exception):
'''
Error in post file
'''
def __init__(self, message, filename, line=None):
super(PostError, self).__init__(self, message)
self.message = message
self.filename = filename
self.line = line
def __repr__(self):
return '%s(%r, %r, %r)' % (self.__class__.__name__, self.exception,
self.filename, self.line)
def __str__(self):
if self.line is None:
return 'Error in post file %s: %s' % (self.filename, self.message)
else:
return 'Error in post file %s line %d: %s' % (self.filename,
self.line, self.message)
class Post(object):
DEFAULT_ENCODING = 'ascii'
DEFAULT_AUTHOR = 'unknown author'
def __init__(self, f):
'''
>>> file_content = """title: test
... date: 2008-1-1
... author: test author
... encoding: utf-8
...
... test."""
>>> from StringIO import StringIO
>>> p = Post(StringIO(file_content))
>>> p
%s
' % escape(x) for x in result)) class Markup(unicode): r"""Marks a string as being safe for inclusion in HTML/XML output without needing to be escaped. This implements the `__html__` interface a couple of frameworks and web applications use. :class:`Markup` is a direct subclass of `unicode` and provides all the methods of `unicode` just that it escapes arguments passed and always returns `Markup`. The `escape` function returns markup objects so that double escaping can't happen. If you want to use autoescaping in Jinja just set the finalizer of the environment to `escape`. The constructor of the :class:`Markup` class can be used for three different things: When passed an unicode object it's assumed to be safe, when passed an object with an HTML representation (has an `__html__` method) that representation is used, otherwise the object passed is converted into a unicode string and then assumed to be safe: >>> Markup("Hello World!") Markup(u'Hello World!') >>> class Foo(object): ... def __html__(self): ... return 'foo' ... >>> Markup(Foo()) Markup(u'foo') If you want object passed being always treated as unsafe you can use the :meth:`escape` classmethod to create a :class:`Markup` object: >>> Markup.escape("Hello World!") Markup(u'Hello <em>World</em>!') Operations on a markup string are markup aware which means that all arguments are passed through the :func:`escape` function: >>> em = Markup("%s") >>> em % "foo & bar" Markup(u'foo & bar') >>> strong = Markup("%(text)s") >>> strong % {'text': ''} Markup(u'<blink>hacker here</blink>') >>> Markup("Hello ") + "