Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

¡Nikola 1.1 en la calle!

Lo es­cri­bí pa­ra es­te mis­mo si­tio, pe­ro de­ci­dí que tal vez sea útil pa­ra otro­s. Los ob­je­ti­vos prin­ci­pa­les de Niko­la so­n:

  • Po­­­co có­­­di­­go: po­r­­que no quie­­ro man­­te­­ner un mon­s­­truo pa­­ra es­­te blo­­­g.

  • Ge­­ne­­ra­­ción rá­­pi­­da de pá­­gi­­na­s: aña­­dir un post no de­­be­­­ría ta­r­­dar mas de 5 se­­gun­­dos en re­­contruir el si­­tio.

  • Ge­­ne­­rar si­­tios es­­tá­­ti­­co­­s: de­­plo­­­y­­ment usan­­do rs­­yn­­c!

  • Ge­­ne­­ra­­ción fle­­xi­­ble de pá­­gi­­na­s: po­­­dés de­­ci­­dir ado­n­­de te­r­­mi­­na ca­­da co­­­sa en el si­­tio.

  • Te­m­­pla­­tes po­­­de­­ro­­sas: Usa Mako

  • Ma­­rkup li­m­­pio pa­­ra los po­s­­ts: Usa Do­­­cu­­tils

  • No ha­­ce bui­l­­ds idio­­­ta­s: Usa doit

  • HT­­ML li­m­­pio por de­­fau­l­­t: Usa boots­­trap

  • Co­­­men­­ta­­rios sin lío­­s: Usa Dis­­qus

  • Tags, con sus pro­­­pios fee­­ds

  • Fá­­cil pa­­ra ha­­cer blogs

  • Pá­­gi­­nas fue­­ra del blog

  • Si­­tios mu­l­­ti­­li­n­­gües

Creo que es­ta ver­sión ini­cial lo­gra esos ob­je­ti­vo­s, pe­ro por su­pues­to es me­jo­ra­ble. Se agra­de­ce el fee­dba­ck!

La pá­gi­na de Niko­la es http://­niko­la-­ge­ne­ra­to­r.­google­co­de.­com

¡Unicode en Python es Divertido!

>>> 'á'.decode('utf8')
u'\xe1'

Sin em­bar­go, hay una tram­pa. Te­nés que es­tar ab­so­lu­ta­men­te se­gu­ro que la co­sa que es­tás de­co­dean­do es un string de by­tes, y no un ob­je­to uni­co­de. Por­que los ob­je­tos uni­co­de tie­nen un mé­to­do de­co­de pe­ro es to­tal­men­te inú­ti­l, y su úni­co pro­pó­si­to en la vi­da es cau­sar es­te error pe­cu­lia­r:

>>> 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)

¿Por­qué es pe­cu­lia­r? Por­que es un error de En­co­de. Cau­sa­do por lla­mar a de­co­de. Lo que pa­sa es que en los ob­je­tos uni­co­de, de­co­de, en la prác­ti­ca es al­go así:

def decode(self, encoding):
    return self.encode('ascii').decode(encoding)

El usua­rio quie­re un ob­je­to uni­co­de. Él tie­ne un ob­je­to uni­cde. Por de­fi­ni­ció­n, no exis­te un co­sa que sea "de­co­dear co­mo utf-8 un ob­je­to uni­co­de". No tie­ne sen­ti­do. Es co­mo pei­nar un pes­ca­do, o es­ca­lar una la­gu­na.

¡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 me­jo­r, no ten­ga­mos un mé­to­do de­co­de en ob­je­tos uni­co­de, que creo es la si­tua­ción en py­thon 3, pe­ro nun­ca lo va a ser en py­thon 2.

Así que aho­ra ya sa­be­n, y bue­na suer­te.

Como se hace

Lo hi­ce por va­rias ra­zo­nes:

  1. Po­r­­que un co­­­men­­ta­­rio pa­­re­­cía su­­ge­­ri­r­­lo ;-)

  2. Po­r­­que es al­­go li­n­­do de ha­­ce­­r. Me gus­­ta reS­­t, me gus­­ta­­ría que lo use más gen­­te, y mo­s­­trar lo fá­­cil que es, es­­tá bue­­no.

  3. Es el ca­­mino del so­­­ftwa­­re li­­bre. Les doy la ma­­ne­­ra pre­­fe­­ri­­da de mo­­­di­­fi­­car mis po­s­­ts.

  4. Era una pa­­va­­da ha­­ce­r­­lo.

Si ven al­gu­na co­sa que fal­te en el blo­g, o les pa­re­ce que quer­da­ría bue­no agre­gar al­go, co­men­ten y ve­mo­s.

Nikola está Cerca

  • Im­­ple­­men­­té tags (i­n­­clu­­yen­­do fee­­ds pa­­ra ca­­da ta­­g).

  • Si­m­­pli­­fi­­qué los te­m­­pla­­tes.

  • Se­­pa­­ré có­­­di­­go y co­n­­fi­­gu­­ra­­ció­­n.

El úl­ti­mo fué el más com­pli­ca­do. Y pa­ra que se vea co­mo es, és­ta es la con­fi­gu­ra­ción com­ple­ta, ex­cep­to pe­da­ci­tos de HT­ML que no va­len la pe­na ve­r, co­mo el có­di­go de google cus­tom sear­ch. ¡Es­pe­ro que sea cla­ro!

# -*- 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")

Contents © 2000-2023 Roberto Alsina