Alice in Deadland (Alice in Deadland, #1)
Review:Not fun and rather shallow. Requires a suspension of disbelief I could not achieve. |
Review:Not fun and rather shallow. Requires a suspension of disbelief I could not achieve. |
Lo escribí para este mismo sitio, pero decidí que tal vez sea útil para otros. Los objetivos principales de Nikola son:
Poco código: porque no quiero mantener un monstruo para este blog.
Generación rápida de páginas: añadir un post no debería tardar mas de 5 segundos en recontruir el sitio.
Generar sitios estáticos: deployment usando rsync!
Generación flexible de páginas: podés decidir adonde termina cada cosa en el sitio.
Templates poderosas: Usa Mako
Markup limpio para los posts: Usa Docutils
No hace builds idiotas: Usa doit
HTML limpio por default: Usa bootstrap
Comentarios sin líos: Usa Disqus
Tags, con sus propios feeds
Fácil para hacer blogs
Páginas fuera del blog
Sitios multilingües
Creo que esta versión inicial logra esos objetivos, pero por supuesto es mejorable. Se agradece el feedback!
La página de Nikola es http://nikola-generator.googlecode.com
>>> 'á'.decode('utf8')
u'\xe1'
Sin embargo, hay una trampa. Tenés que estar absolutamente seguro que la cosa que estás decodeando es un string de bytes, y no un objeto unicode. Porque los objetos unicode tienen un método decode pero es totalmente inútil, y su único propósito en la vida es causar este error peculiar:
>>> u'á'.decode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1'
in position 0: ordinal not in range(128)
¿Porqué es peculiar? Porque es un error de Encode. Causado por llamar a decode. Lo que pasa es que en los objetos unicode, decode, en la práctica es algo así:
def decode(self, encoding):
return self.encode('ascii').decode(encoding)
El usuario quiere un objeto unicode. Él tiene un objeto unicde. Por definición, no existe un cosa que sea "decodear como utf-8 un objeto unicode". No tiene sentido. Es como peinar un pescado, o escalar una laguna.
¡Lo que debería devolver es self
! Además es suamente molesto que la
única manera de evitar el error es chequear el tipo del objeto, lo que es
activamente antipitónico.
Aún mejor, no tengamos un método decode en objetos unicode, que creo es la situación en python 3, pero nunca lo va a ser en python 2.
Así que ahora ya saben, y buena suerte.
Lo hice por varias razones:
Porque un comentario parecía sugerirlo ;-)
Porque es algo lindo de hacer. Me gusta reSt, me gustaría que lo use más gente, y mostrar lo fácil que es, está bueno.
Es el camino del software libre. Les doy la manera preferida de modificar mis posts.
Era una pavada hacerlo.
Si ven alguna cosa que falte en el blog, o les parece que querdaría bueno agregar algo, comenten y vemos.
Implementé tags (incluyendo feeds para cada tag).
Simplifiqué los templates.
Separé código y configuración.
El último fué el más complicado. Y para que se vea como es, ésta es la configuración completa, excepto pedacitos de HTML que no valen la pena ver, como el código de google custom search. ¡Espero que sea claro!
# -*- coding: utf-8 -*-
# post_pages contains (wildcard, destination, template) tuples.
#
# The wildcard is used to generate a list of reSt source files (whatever/thing.txt)
# That fragment must have an associated metadata file (whatever/thing.meta),
# and opcionally translated files (example for spanish, with code "es"):
# whatever/thing.txt.es and whatever/thing.meta.es
#
# From those files, a set of HTML fragment files will be generated:
# whatever/thing.html (and maybe whatever/thing.html.es)
#
# These files are combinated with the template to produce rendered
# pages, which will be placed at
# output / TRANSLATIONS[lang] / destination / pagename.html
#
# where "pagename" is specified in the metadata file.
#
post_pages = (
("posts/*.txt", "weblog/posts", "post.tmpl"),
("stories/*.txt", "stories", "post.tmpl"),
)
# What is the default language?
DEFAULT_LANG = "en"
# What languages do you have?
# If a specific post is not translated to a language, then the version
# in the default language will be shown instead.
# The format is {"translationcode" : "path/to/translation" }
# the path will be used as a prefix for the generated pages location
TRANSLATIONS = {
"en": "",
"es": "tr/es",
}
# Data about this site
BLOG_TITLE = "Lateral Opinion"
BLOG_URL = "//ralsina.me"
BLOG_EMAIL = "ralsina@kde.org"
BLOG_DESCRIPTION = "I write free software. I have an opinion on almost "\
"everything. I write quickly. A weblog was inevitable."
# Paths for different autogenerated bits. These are combined with the translation
# paths.
# Final locations are:
# output / TRANSLATION[lang] / TAG_PATH / index.html (list of tags)
# output / TRANSLATION[lang] / TAG_PATH / tag.html (list of posts for a tag)
# output / TRANSLATION[lang] / TAG_PATH / tag.xml (RSS feed for a tag)
TAG_PATH = "categories"
# Final location is output / TRANSLATION[lang] / INDEX_PATH / index-*.html
INDEX_PATH = "weblog"
# Final locations for the archives are:
# output / TRANSLATION[lang] / ARCHIVE_PATH / archive.html
# output / TRANSLATION[lang] / ARCHIVE_PATH / YEAR / index.html
ARCHIVE_PATH = "weblog"
# Final locations are:
# output / TRANSLATION[lang] / RSS_PATH / rss.xml
RSS_PATH = "weblog"
# A HTML fragment describing the license, for the sidebar.
LICENSE = """
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/ar/">
<img alt="Creative Commons License" style="border-width:0; margin-bottom:12px;"
src="http://i.creativecommons.org/l/by-nc-sa/2.5/ar/88x31.png"></a>
"""
# A search form to search this site, for the sidebar. Has to be a <li>
# for the default template (base.tmpl).
SEARCH_FORM = """
<!-- google custom search -->
<!-- End of google custom search -->
"""
# Google analytics or whatever else you use. Added to the bottom of <body>
# in the default template (base.tmpl).
ANALYTICS = """
<!-- Start of StatCounter Code -->
<!-- End of StatCounter Code -->
<!-- Start of Google Analytics -->
<!-- End of Google Analytics -->
"""
# Put in global_context things you want available on all your templates.
# It can be anything, data, functions, modules, etc.
GLOBAL_CONTEXT = {
'analytics': ANALYTICS,
'blog_title': BLOG_TITLE,
'blog_url': BLOG_URL,
'translations': TRANSLATIONS,
'license': LICENSE,
'search_form': SEARCH_FORM,
# Locale-dependent links
'archives_link': {
'es': '<a href="/tr/es/weblog/archive.html">Archivo</a>',
'en': '<a href="/weblog/archive.html">Archives</a>',
},
'tags_link': {
'es': '<a href="/tr/es/categories/index.html">Tags</a>',
'en': '<a href="/categories/index.html">Tags</a>',
},
}
execfile("nikola/nikola.py")