diff --git a/THANKS b/THANKS index 1d867471..15503473 100644 --- a/THANKS +++ b/THANKS @@ -4,7 +4,7 @@ contributed or implemented key features over time. We do our best to keep this list up-to-date, but you can also have a look at the nice contributor graphs produced by GitHub: https://github.com/getpelican/pelican/graphs/contributors -If you want to contibute, check the documentation section about how to do so: +If you want to contribute, check the documentation section about how to do so: Aaron Kavlie diff --git a/docs/changelog.rst b/docs/changelog.rst index d8c33cb5..52367cec 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,34 @@ Release history ############### +3.5.0 (2014-11-04) +================== + +* Introduce ``ARTICLE_ORDER_BY`` and ``PAGE_ORDER_BY`` settings to control the + order of articles and pages. +* Include time zone information in dates rendered in templates. +* Expose the reader name in the metadata for articles and pages. +* Add the ability to store static files along with content in the same + directory as articles and pages using ``{attach}`` in the path. +* Prevent Pelican from raising an exception when there are duplicate pieces of + metadata in a Markdown file. +* Introduce the ``TYPOGRIFY_IGNORE_TAGS`` setting to add HTML tags to be ignored + by Typogrify. +* Add the ability to use ``-`` in date formats to strip leading zeros. For + example, ``%-d/%-m/%y`` will now result in the date ``9/8/12``. +* Ensure feed generation is correctly disabled during quickstart configuration. +* Fix ``PAGE_EXCLUDES`` and ``ARTICLE_EXCLUDES`` from incorrectly matching + sub-directories. +* Introduce ``STATIC_EXCLUDE`` setting to add static file excludes. +* Fix an issue when using ``PAGINATION_PATTERNS`` while ``RELATIVE_URLS`` + is enabled. +* Fix feed generation causing links to use the wrong language for month + names when using other locales. +* Fix an issue where the authors list in the simple template wasn't correctly + formatted. +* Fix an issue when parsing non-string URLs from settings. +* Improve consistency of debug and warning messages. + 3.4.0 (2014-07-01) ================== diff --git a/docs/content.rst b/docs/content.rst index ad81bed1..4de480ba 100644 --- a/docs/content.rst +++ b/docs/content.rst @@ -43,8 +43,13 @@ Pelican implements an extension to reStructuredText to enable support for the You can also use Markdown syntax (with a file ending in ``.md``, ``.markdown``, ``.mkd``, or ``.mdown``). Markdown generation requires that you first explicitly install the ``Markdown`` package, which can be done via ``pip -install Markdown``. Metadata syntax for Markdown posts should follow this -pattern:: +install Markdown``. + +Pelican also supports `Markdown Extensions`_, which might have to be installed +separately if they are not included in the default ``Markdown`` package and can +be configured and loaded via the ``MD_EXTENSIONS`` setting. + +Metadata syntax for Markdown posts should follow this pattern:: Title: My super title Date: 2010-12-03 10:20 @@ -95,6 +100,13 @@ not be a good category name, you can set the setting ``USE_FOLDER_AS_CATEGORY`` to ``False``. When parsing dates given in the page metadata, Pelican supports the W3C's `suggested subset ISO 8601`__. +.. note:: + + When experimenting with different settings (especially the metadata + ones) caching may interfere and the changes may not be visible. In + such cases disable caching with ``LOAD_CONTENT_CACHE = False`` or + use the ``--ignore-cache`` command-line switch. + __ `W3C ISO 8601`_ ``modified`` should be last time you updated the article, and defaults to ``date`` if not specified. @@ -139,24 +151,25 @@ Linking to internal content From Pelican 3.1 onwards, it is now possible to specify intra-site links to files in the *source content* hierarchy instead of files in the *generated* -hierarchy. This makes it easier to link from the current post to other posts -and images that may be sitting alongside the current post (instead of having -to determine where those resources will be placed after site generation). +hierarchy. This makes it easier to link from the current post to other content +that may be sitting alongside that post (instead of having to determine where +the other content will be placed after site generation). To link to internal content (files in the ``content`` directory), use the -following syntax: ``{filename}path/to/file``:: +following syntax for the link target: ``{filename}path/to/file`` +For example, a Pelican project might be structured like this:: website/ ├── content - │   ├── article1.rst - │   ├── cat/ - │   │   └── article2.md + │   ├── category/ + │   │   └── article1.rst + │   ├── article2.md │ └── pages │      └── about.md └── pelican.conf.py -In this example, ``article1.rst`` could look like:: +In this example, ``article1.rst`` could look like this:: The first article ################# @@ -165,8 +178,8 @@ In this example, ``article1.rst`` could look like:: See below intra-site link examples in reStructuredText format. - `a link relative to content root <{filename}/cat/article2.rst>`_ - `a link relative to current file <{filename}cat/article2.rst>`_ + `a link relative to the current file <{filename}../article2.md>`_ + `a link relative to the content root <{filename}/article2.md>`_ and ``article2.md``:: @@ -175,43 +188,154 @@ and ``article2.md``:: See below intra-site link examples in Markdown format. - [a link relative to content root]({filename}/article1.md) - [a link relative to current file]({filename}../article1.md) + [a link relative to the current file]({filename}category/article1.rst) + [a link relative to the content root]({filename}/category/article1.rst) -Embedding non-article or non-page content is slightly different in that the -directories need to be specified in ``pelicanconf.py`` file. The ``images`` -directory is configured for this by default but others will need to be added -manually:: +Linking to static files +----------------------- + +Linking to non-article or non-page content uses the same ``{filename}`` syntax +as described above. It is important to remember that those files will not be +copied to the output directory unless the source directories containing them +are included in the ``STATIC_PATHS`` setting of the project's ``pelicanconf.py`` +file. Pelican's default configuration includes the ``images`` directory for +this, but others must be added manually. Forgetting to do so will result in +broken links. + +For example, a project's content directory might be structured like this:: content ├── images │   └── han.jpg - └── misc -    └── image-test.md + ├── pdfs + │   └── menu.pdf + └── pages +    └── test.md -And ``image-test.md`` would include:: +``test.md`` would include:: ![Alt Text]({filename}/images/han.jpg) + [Our Menu]({filename}/pdfs/menu.pdf) -Any content can be linked in this way. What happens is that the ``images`` -directory gets copied to ``output/`` during site generation because Pelican -includes ``images`` in the ``STATIC_PATHS`` setting's list by default. If -you want to have another directory, say ``pdfs``, copied from your content to -your output during site generation, you would need to add the following to -your settings file:: +``pelicanconf.py`` would include:: STATIC_PATHS = ['images', 'pdfs'] -After the above line has been added, subsequent site generation should copy the -``content/pdfs/`` directory to ``output/pdfs/``. +Site generation would then copy ``han.jpg`` to ``output/images/han.jpg``, +``menu.pdf`` to ``output/pdfs/menu.pdf``, and write the appropriate links +in ``test.md``. -You can also link to categories or tags, using the ``{tag}tagname`` and +Mixed content in the same directory +----------------------------------- + +Starting with Pelican 3.5, static files can safely share a source directory with +page source files, without exposing the page sources in the generated site. +Any such directory must be added to both ``STATIC_PATHS`` and ``PAGE_PATHS`` +(or ``STATIC_PATHS`` and ``ARTICLE_PATHS``). Pelican will identify and process +the page source files normally, and copy the remaining files as if they lived +in a separate directory reserved for static files. + +Note: Placing static and content source files together in the same source +directory does not guarantee that they will end up in the same place in the +generated site. The easiest way to do this is by using the ``{attach}`` link +syntax (described below). Alternatively, the ``STATIC_SAVE_AS``, +``PAGE_SAVE_AS``, and ``ARTICLE_SAVE_AS`` settings (and the corresponding +``*_URL`` settings) can be configured to place files of different types +together, just as they could in earlier versions of Pelican. + +Attaching static files +---------------------- + +Starting with Pelican 3.5, static files can be "attached" to a page or article +using this syntax for the link target: ``{attach}path/to/file`` This works +like the ``{filename}`` syntax, but also relocates the static file into the +linking document's output directory. If the static file originates from a +subdirectory beneath the linking document's source, that relationship will be +preserved on output. Otherwise, it will become a sibling of the linking +document. + +This only works for linking to static files, and only when they originate from +a directory included in the ``STATIC_PATHS`` setting. + +For example, a project's content directory might be structured like this:: + + content + ├── blog + │   ├── icons + │   │   └── icon.png + │   ├── photo.jpg + │   └── testpost.md + └── downloads + └── archive.zip + +``pelicanconf.py`` would include:: + + PATH = 'content' + STATIC_PATHS = ['blog', 'downloads'] + ARTICLE_PATHS = ['blog'] + ARTICLE_SAVE_AS = '{date:%Y}/{slug}.html' + ARTICLE_URL = '{date:%Y}/{slug}.html' + +``testpost.md`` would include:: + + Title: Test Post + Category: test + Date: 2014-10-31 + + ![Icon]({attach}icons/icon.png) + ![Photo]({attach}photo.jpg) + [Downloadable File]({attach}/downloads/archive.zip) + +Site generation would then produce an output directory structured like this:: + + output + └── 2014 + ├── archive.zip + ├── icons + │   └── icon.png + ├── photo.jpg + └── test-post.html + +Notice that all the files linked using ``{attach}`` ended up in or beneath +the article's output directory. + +If a static file is linked multiple times, the relocating feature of +``{attach}`` will only work in the first of those links to be processed. +After the first link, Pelican will treat ``{attach}`` like ``{filename}``. +This avoids breaking the already-processed links. + +**Be careful when linking to a file from multiple documents:** +Since the first link to a file finalizes its location and Pelican does +not define the order in which documents are processed, using ``{attach}`` on a +file linked by multiple documents can cause its location to change from one +site build to the next. (Whether this happens in practice will depend on the +operating system, file system, version of Pelican, and documents being added, +modified, or removed from the project.) Any external sites linking to the +file's old location might then find their links broken. **It is therefore +advisable to use {attach} only if you use it in all links to a file, and only +if the linking documents share a single directory.** Under these conditions, +the file's output location will not change in future builds. In cases where +these precautions are not possible, consider using ``{filename}`` links instead +of ``{attach}``, and letting the file's location be determined by the project's +``STATIC_SAVE_AS`` and ``STATIC_URL`` settings. (Per-file ``save_as`` and +``url`` overrides can still be set in ``EXTRA_PATH_METADATA``.) + +Linking to tags and categories +------------------------------ + +You can link to tags and categories using the ``{tag}tagname`` and ``{category}foobar`` syntax. -For backward compatibility, Pelican also supports bars (``||``) in addition to -curly braces (``{}``). For example: ``|filename|an_article.rst``, -``|tag|tagname``, ``|category|foobar``. The syntax was changed from ``||`` to -``{}`` to avoid collision with Markdown extensions or reST directives. +Deprecated internal link syntax +------------------------------- + +To remain compatible with earlier versions, Pelican still supports vertical bars +(``||``) in addition to curly braces (``{}``) for internal links. For example: +``|filename|an_article.rst``, ``|tag|tagname``, ``|category|foobar``. +The syntax was changed from ``||`` to ``{}`` to avoid collision with Markdown +extensions or reST directives. Support for the old syntax may eventually be +removed. + Importing an existing site ========================== @@ -228,6 +352,13 @@ English [en] by default). With those settings in place, only articles with the default language will be listed, and each article will be accompanied by a list of available translations for that article. +.. note:: + + This core Pelican functionality does not create sub-sites + (e.g. ``example.com/de``) with translated templates for each + language. For such advanced functionality the `i18n_subsites + plugin`_ can be used. + Pelican uses the article's URL "slug" to determine if two or more articles are translations of one another. The slug can be set manually in the file's metadata; if not set explicitly, Pelican will auto-generate the slug from the @@ -367,6 +498,15 @@ publishing, for example), you can add a ``Status: draft`` attribute to its metadata. That article will then be output to the ``drafts`` folder and not listed on the index page nor on any category or tag page. +If your articles should be automatically published as a draft (to not accidentally +publish an article before it is finished) include the status in the ``DEFAULT_METADATA``:: + + DEFAULT_METADATA = { + 'status': 'draft', + } + .. _W3C ISO 8601: http://www.w3.org/TR/NOTE-datetime .. _AsciiDoc: http://www.methods.co.nz/asciidoc/ .. _pelican-plugins: http://github.com/getpelican/pelican-plugins +.. _Markdown Extensions: http://pythonhosted.org/Markdown/extensions/ +.. _i18n_subsites plugin: http://github.com/getpelican/pelican-plugins/tree/master/i18n_subsites diff --git a/docs/contribute.rst b/docs/contribute.rst index 7c117d26..2962ddb1 100644 --- a/docs/contribute.rst +++ b/docs/contribute.rst @@ -202,5 +202,5 @@ Try to limit them to ``--debug`` mode like the following:: try: some_action() except Exception as e: - logger.error('Exception occured: %s', e, + logger.error('Exception occurred: %s', e, exc_info=settings.get('DEBUG', False)) diff --git a/docs/faq.rst b/docs/faq.rst index 1376511a..c749c262 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -32,6 +32,14 @@ Configuration files are optional and are just an easy way to configure Pelican. For basic operations, it's possible to specify options while invoking Pelican via the command line. See ``pelican --help`` for more information. +Changes to the setting file take no effect +========================================== + +When experimenting with different settings (especially the metadata +ones) caching may interfere and the changes may not be visible. In +such cases disable caching with ``LOAD_CONTENT_CACHE = False`` or +use the ``--ignore-cache`` command-line switch. + I'm creating my own theme. How do I use Pygments for syntax highlighting? ========================================================================= @@ -135,6 +143,10 @@ your home page. The following Markdown example could be stored in Thank you for visiting. Welcome! +If the original blog index is still wanted, it can then be saved in a +different location by setting ``INDEX_SAVE_AS = 'blog_index.html`` for +the ``''index'`` direct template. + What if I want to disable feed generation? ========================================== @@ -220,3 +232,12 @@ When only several specific output files are of interest (e.g. when working on some specific page or the theme templates), the `WRITE_SELECTED` option may help, see :ref:`writing_only_selected_content`. + +How to process only a subset of all articles? +============================================= + +It is often useful to process only e.g. 10 articles for debugging +purposes. This can be achieved by explicitly specifying only the +filenames of those articles in ``ARTICLE_PATHS``. A list of such +filenames could be found using a command similar to ``cd content; +find -name '*.md' | head -n 10``. diff --git a/docs/importer.rst b/docs/importer.rst index 309ca144..aa3fa935 100644 --- a/docs/importer.rst +++ b/docs/importer.rst @@ -47,10 +47,11 @@ Usage Positional arguments -------------------- - - input The input file to read - api_token [Posterous only] api_token can be obtained from http://posterous.com/api/ - api_key [Tumblr only] api_key can be obtained from http://www.tumblr.com/oauth/apps + ============= ============================================================================ + ``input`` The input file to read + ``api_token`` (Posterous only) api_token can be obtained from http://posterous.com/api/ + ``api_key`` (Tumblr only) api_key can be obtained from http://www.tumblr.com/oauth/apps + ============= ============================================================================ Optional arguments ------------------ diff --git a/docs/plugins.rst b/docs/plugins.rst index 01e67810..15fcf109 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -20,6 +20,14 @@ Alternatively, another method is to import them and add them to the list:: from package import myplugin PLUGINS = [myplugin,] +.. note:: + + When experimenting with different plugins (especially the ones that + deal with metadata and content) caching may interfere and the + changes may not be visible. In such cases disable caching with + ``LOAD_CONTENT_CACHE = False`` or use the ``--ignore-cache`` + command-line switch. + If your plugins are not in an importable path, you can specify a list of paths via the ``PLUGIN_PATHS`` setting. As shown in the following example, paths in the ``PLUGIN_PATHS`` list can be absolute or relative to the settings file:: @@ -57,6 +65,12 @@ which you map the signals to your plugin logic. Let's take a simple example:: def register(): signals.initialized.connect(test) +.. note:: + + Signal receivers are weakly-referenced and thus must not be defined within + your ``register`` callable or they will be garbage-collected before the + signal is emitted. + List of signals =============== @@ -67,7 +81,7 @@ Signal Arguments Description ================================= ============================ =========================================================================== initialized pelican object finalized pelican object invoked after all the generators are executed and just before pelican exits - usefull for custom post processing actions, such as: + useful for custom post processing actions, such as: - minifying js/css assets. - notify/ping search engines with an updated sitemap. generator_init generator invoked in the Generator.__init__ diff --git a/docs/publish.rst b/docs/publish.rst index 266009e4..fea053bf 100644 --- a/docs/publish.rst +++ b/docs/publish.rst @@ -36,12 +36,19 @@ HTML files directly:: Because the above method may have trouble locating your CSS and other linked assets, running a simple web server using Python will often provide a more -reliable previewing experience:: +reliable previewing experience. + +For Python 2, run:: cd output python -m SimpleHTTPServer -Once the ``SimpleHTTPServer`` has been started, you can preview your site at +For Python 3, run:: + + cd output + python -m http.server + +Once the basic server has been started, you can preview your site at http://localhost:8000/ Deployment diff --git a/docs/quickstart.rst b/docs/quickstart.rst index fb90b002..4fe75d98 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -7,8 +7,9 @@ impatient, following are some quick steps to get started. Installation ------------ -Install Pelican on Python 2.7.x or Python 3.3+ by running the following command -in your preferred terminal, prefixing with ``sudo`` if permissions warrant:: +Install Pelican (and optionally Markdown if you intend to use it) on Python +2.7.x or Python 3.3+ by running the following command in your preferred +terminal, prefixing with ``sudo`` if permissions warrant:: pip install pelican markdown diff --git a/docs/settings.rst b/docs/settings.rst index 7a3f08e6..02f4359f 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -4,11 +4,18 @@ Settings Pelican is configurable thanks to a settings file you can pass to the command line:: - pelican content -s path/to/your/settingsfile.py + pelican content -s path/to/your/pelicanconf.py (If you used the ``pelican-quickstart`` command, your primary settings file will be named ``pelicanconf.py`` by default.) +.. note:: + + When experimenting with different settings (especially the metadata + ones) caching may interfere and the changes may not be visible. In + such cases disable caching with ``LOAD_CONTENT_CACHE = False`` or + use the ``--ignore-cache`` command-line switch. + Settings are configured in the form of a Python module (a file). There is an `example settings file `_ @@ -28,6 +35,7 @@ templates, which allows you to use your settings to add site-wide content. Here is a list of settings for Pelican: + Basic settings ============== @@ -117,10 +125,12 @@ Setting name (followed by default value, if any) ``PATH`` Path to content directory to be processed by Pelican. If undefined, and content path is not specified via an argument to the ``pelican`` command, Pelican will use the current working directory. -``PAGE_PATHS = ['pages']`` A list of directories to look at for pages, relative to ``PATH``. +``PAGE_PATHS = ['pages']`` A list of directories and files to look at for pages, + relative to ``PATH``. ``PAGE_EXCLUDES = []`` A list of directories to exclude when looking for pages in addition to ``ARTICLE_PATHS``. -``ARTICLE_PATHS = ['']`` A list of directories to look at for articles, relative to ``PATH``. +``ARTICLE_PATHS = ['']`` A list of directories and files to look at for articles, + relative to ``PATH``. ``ARTICLE_EXCLUDES = []`` A list of directories to exclude when looking for articles in addition to ``PAGE_PATHS``. ``OUTPUT_SOURCES = False`` Set to True if you want to copy the articles and pages in their @@ -142,10 +152,15 @@ Setting name (followed by default value, if any) slash at the end. Example: ``SITEURL = 'http://mydomain.com'`` ``TEMPLATE_PAGES = None`` A mapping containing template pages that will be rendered with the blog entries. See :ref:`template_pages`. -``STATIC_PATHS = ['images']`` The static paths you want to have accessible - on the output path "static". By default, - Pelican will copy the "images" folder to the - output folder. +``STATIC_PATHS = ['images']`` A list of directories (relative to ``PATH``) in which to look for + static files. Such files will be copied to the output directory + without modification. Articles, pages, and other content source + files will normally be skipped, so it is safe for a directory to + appear both here and in ``PAGE_PATHS`` or ``ARTICLE_PATHS``. + Pelican's default settings include the "images" directory here. +``STATIC_EXCLUDES = []`` A list of directories to exclude when looking for static files. +``STATIC_EXCLUDE_SOURCES = True`` If set to False, content source files will not be skipped when + copying files found in ``STATIC_PATHS``. ``TIMEZONE`` The timezone used in the date information, to generate Atom and RSS feeds. See the *Timezone* section below for more info. @@ -220,9 +235,9 @@ configuration files for local development and publishing, respectively. You can customize the URLs and locations where files will be saved. The ``*_URL`` and ``*_SAVE_AS`` variables use Python's format strings. These variables allow you to place your articles in a location such as -``{slug}/index.html`` and link to them as ``{slug}`` for clean URLs. These -settings give you the flexibility to place your articles and pages anywhere you -want. +``{slug}/index.html`` and link to them as ``{slug}`` for clean URLs (see +example below). These settings give you the flexibility to place your articles +and pages anywhere you want. .. note:: If you specify a ``datetime`` directive, it will be substituted using the @@ -245,30 +260,12 @@ Example usage: * ``ARTICLE_URL = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/'`` * ``ARTICLE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/index.html'`` +* ``PAGE_URL = 'pages/{slug}/'`` +* ``PAGE_SAVE_AS = 'pages/{slug}/index.html'`` -This would save your articles in something like ``/posts/2011/Aug/07/sample-post/index.html``, -and the URL to this would be ``/posts/2011/Aug/07/sample-post/``. - -Pelican can optionally create per-year, per-month, and per-day archives of your -posts. These secondary archives are disabled by default but are automatically -enabled if you supply format strings for their respective ``_SAVE_AS`` settings. -Period archives fit intuitively with the hierarchical model of web URLs and can -make it easier for readers to navigate through the posts you've written over time. - -Example usage: - -* ``YEAR_ARCHIVE_SAVE_AS = 'posts/{date:%Y}/index.html'`` -* ``MONTH_ARCHIVE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/index.html'`` - -With these settings, Pelican will create an archive of all your posts for the -year at (for instance) ``posts/2011/index.html`` and an archive of all your -posts for the month at ``posts/2011/Aug/index.html``. - -.. note:: - Period archives work best when the final path segment is ``index.html``. - This way a reader can remove a portion of your URL and automatically - arrive at an appropriate archive of posts, without having to specify - a page name. +This would save your articles into something like ``/posts/2011/Aug/07/sample-post/index.html``, +save your pages into ``/pages/about/index.html``, and render them available at +URLs of ``/posts/2011/Aug/07/sample-post/`` and ``/pages/about/``, respectively. ====================================================== ============================================================== Setting name (followed by default value, if any) What does it do? @@ -334,22 +331,49 @@ Setting name (followed by default value, if any) What does it do? set the corresponding ``*_SAVE_AS`` setting to ``''`` to prevent the relevant page from being generated. +Pelican can optionally create per-year, per-month, and per-day archives of your +posts. These secondary archives are disabled by default but are automatically +enabled if you supply format strings for their respective ``_SAVE_AS`` settings. +Period archives fit intuitively with the hierarchical model of web URLs and can +make it easier for readers to navigate through the posts you've written over time. + +Example usage: + +* ``YEAR_ARCHIVE_SAVE_AS = 'posts/{date:%Y}/index.html'`` +* ``MONTH_ARCHIVE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/index.html'`` + +With these settings, Pelican will create an archive of all your posts for the +year at (for instance) ``posts/2011/index.html`` and an archive of all your +posts for the month at ``posts/2011/Aug/index.html``. + +.. note:: + Period archives work best when the final path segment is ``index.html``. + This way a reader can remove a portion of your URL and automatically + arrive at an appropriate archive of posts, without having to specify + a page name. + ``DIRECT_TEMPLATES``, which are ``('index', 'tags', 'categories', 'archives')`` by default, work a bit differently than noted above. Only the ``_SAVE_AS`` -settings are available: +settings are available, but it is available for any direct template. -============================================= =============================================== +============================================= ====================================================== Setting name (followed by default value) What does it do? -============================================= =============================================== +============================================= ====================================================== ``ARCHIVES_SAVE_AS = 'archives.html'`` The location to save the article archives page. +``YEAR_ARCHIVE_SAVE_AS = ''`` The location to save per-year archives of your posts. +``MONTH_ARCHIVE_SAVE_AS = ''`` The location to save per-month archives of your posts. +``DAY_ARCHIVE_SAVE_AS = ''`` The location to save per-day archives of your posts. ``AUTHORS_SAVE_AS = 'authors.html'`` The location to save the author list. ``CATEGORIES_SAVE_AS = 'categories.html'`` The location to save the category list. ``TAGS_SAVE_AS = 'tags.html'`` The location to save the tag list. -============================================= =============================================== +``INDEX_SAVE_AS = 'index.html'`` The location to save the list of all articles. +============================================= ====================================================== -URLs for direct template pages are theme-dependent. Some themes hard-code them: +URLs for direct template pages are theme-dependent. Some themes use +corresponding ``*_URL`` setting as string, while others hard-code them: ``'archives.html'``, ``'authors.html'``, ``'categories.html'``, ``'tags.html'``. + Timezone -------- @@ -423,6 +447,7 @@ can get a list of available locales via the ``locale -a`` command; see manpage .. _template_pages: + Template pages ============== @@ -440,6 +465,7 @@ your resume, and a contact page — you could have:: .. _path_metadata: + Path metadata ============= @@ -473,16 +499,17 @@ particular file: # STATIC_SAVE_AS = '{path}' # STATIC_URL = '{path}' STATIC_PATHS = [ - 'extra/robots.txt', + 'static/robots.txt', ] EXTRA_PATH_METADATA = { - 'extra/robots.txt': {'path': 'robots.txt'}, + 'static/robots.txt': {'path': 'robots.txt'}, } __ internal_metadata__ .. _group name notation: http://docs.python.org/3/library/re.html#regular-expression-syntax + Feed settings ============= @@ -525,6 +552,7 @@ If you don't want to generate some or any of these feeds, set the above variable .. [2] %s is the name of the category. + FeedBurner ---------- @@ -544,6 +572,7 @@ Address". In this example, the "Original Feed" would be ``http://www.example.com/thymefeeds/main.xml`` and the "Feed Address" suffix would be ``thymefeeds/main.xml``. + Pagination ========== @@ -567,6 +596,7 @@ Setting name (followed by default value, if any) What does it do? pagination output. ================================================ ===================================================== + Using Pagination Patterns ------------------------- @@ -589,6 +619,7 @@ This would cause the first page to be written to ``{base_name}/index.html``, and subsequent ones would be written into ``page/{number}`` directories. + Tag cloud ========= @@ -635,6 +666,7 @@ For example:: ... + Translations ============ @@ -651,6 +683,7 @@ Setting name (followed by default value, if any) What does it do? .. [3] %s is the language + Ordering content ================ @@ -663,6 +696,7 @@ Setting name (followed by default value) What does it do? alphabetical order; default lists alphabetically.) ================================================ ===================================================== + Themes ====== @@ -747,6 +781,7 @@ adding the following to your configuration:: CSS_FILE = "wide.css" + Logging ======= @@ -764,6 +799,7 @@ For example: ``[(logging.WARN, 'TAG_SAVE_AS is set to False')]`` .. _reading_only_modified_content: + Reading only modified content ============================= @@ -830,6 +866,7 @@ from the ``--checksum`` option. .. _writing_only_selected_content: + Writing only selected content ============================= @@ -843,6 +880,7 @@ on the command line using the ``--write-selected`` option, which accepts a comma-separated list of output file paths. By default this list is empty, so all output is written. + Example settings ================ diff --git a/docs/themes.rst b/docs/themes.rst index 4be9a8e5..198f8334 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -16,6 +16,7 @@ then modified), you can specify that theme via the ``-t`` flag:: If you'd rather not specify the theme on every invocation, you can define ``THEME`` in your settings to point to the location of your preferred theme. + Structure ========= @@ -32,7 +33,7 @@ To make your own theme, you must follow the following structure:: ├── authors.html // must list all the authors ├── categories.html // must list all the categories ├── category.html // processed for each category - ├── index.html // the index. List all the articles + ├── index.html // the index (list all the articles) ├── page.html // processed for each page ├── tag.html // processed for each tag └── tags.html // must list all the tags. Can be a tag cloud. @@ -45,6 +46,7 @@ To make your own theme, you must follow the following structure:: The template files listed above are mandatory; you can add your own templates if it helps you keep things organized while creating your theme. + Templates and variables ======================= @@ -55,6 +57,7 @@ variables will be passed to each template at generation time. All templates will receive the variables defined in your settings file, as long as they are in all-caps. You can access them directly. + Common variables ---------------- @@ -64,7 +67,7 @@ All of these settings will be available to all templates. Variable Description ============= =================================================== output_file The name of the file currently being generated. For - instance, when Pelican is rendering the homepage, + instance, when Pelican is rendering the home page, output_file will be "index.html". articles The list of articles, ordered descending by date. All the elements are `Article` objects, so you can @@ -81,6 +84,7 @@ categories A list of (category, articles) tuples, containing pages The list of pages ============= =================================================== + Sorting ------- @@ -112,12 +116,13 @@ to the locale given in your settings:: .. _datetime: http://docs.python.org/2/library/datetime.html#datetime-objects .. _strftime: http://docs.python.org/2/library/datetime.html#strftime-strptime-behavior + index.html ---------- -This is the home page of your blog, generated at output/index.html. +This is the home page or index of your blog, generated at ``index.html``. -If pagination is active, subsequent pages will reside in output/index`n`.html. +If pagination is active, subsequent pages will reside in ``index{number}.html``. ====================== =================================================== Variable Description @@ -139,14 +144,14 @@ dates_next_page The next page of articles, ordered by date, page_name 'index' -- useful for pagination links ====================== =================================================== + author.html ------------- This template will be processed for each of the existing authors, with -output generated at output/author/`author_name`.html. - -If pagination is active, subsequent pages will reside as defined by setting -AUTHOR_SAVE_AS (`Default:` output/author/`author_name'n'`.html). +output generated according to the ``AUTHOR_SAVE_AS`` setting (`Default:` +``author/{author_name}.html``). If pagination is active, subsequent pages will by +default reside at ``author/{author_name}{number}.html``. ====================== =================================================== Variable Description @@ -173,14 +178,14 @@ page_name AUTHOR_URL where everything after `{slug}` is removed -- useful for pagination links ====================== =================================================== + category.html ------------- This template will be processed for each of the existing categories, with -output generated at output/category/`category_name`.html. - -If pagination is active, subsequent pages will reside as defined by setting -CATEGORY_SAVE_AS (`Default:` output/category/`category_name'n'`.html). +output generated according to the ``CATEGORY_SAVE_AS`` setting (`Default:` +``category/{category_name}.html``). If pagination is active, subsequent pages will by +default reside at ``category/{category_name}{number}.html``. ====================== =================================================== Variable Description @@ -207,11 +212,14 @@ page_name CATEGORY_URL where everything after `{slug}` is removed -- useful for pagination links ====================== =================================================== + article.html ------------- -This template will be processed for each article, with .html files saved -as output/`article_name`.html. Here are the specific variables it gets. +This template will be processed for each article, with +output generated according to the ``ARTICLE_SAVE_AS`` setting (`Default:` +``{article_name}.html``). The following variables are available when +rendering. ============= =================================================== Variable Description @@ -249,8 +257,10 @@ image for the Facebook open graph tags that will change for each article: page.html --------- -This template will be processed for each page, with corresponding .html files -saved as output/`page_name`.html. +This template will be processed for each page, with +output generated according to the ``PAGE_SAVE_AS`` setting (`Default:` +``pages/{page_name}.html``). The following variables are available when +rendering. ============= =================================================== Variable Description @@ -259,14 +269,14 @@ page The page object to be displayed. You can access its title, slug, and content. ============= =================================================== + tag.html -------- -This template will be processed for each tag, with corresponding .html files -saved as output/tag/`tag_name`.html. - -If pagination is active, subsequent pages will reside as defined in setting -TAG_SAVE_AS (`Default:` output/tag/`tag_name'n'`.html). +This template will be processed for each tag, with +output generated according to the ``TAG_SAVE_AS`` setting (`Default:` +``tag/{tag_name}.html``). If pagination is active, subsequent pages will by +default reside at ``tag/{tag_name}{number}.html``. ====================== =================================================== Variable Description @@ -293,12 +303,13 @@ page_name TAG_URL where everything after `{slug}` is removed -- useful for pagination links ====================== =================================================== + period_archives.html -------------------- This template will be processed for each year of your posts if a path -for YEAR_ARCHIVE_SAVE_AS is defined, each month if MONTH_ARCHIVE_SAVE_AS -is defined and each day if DAY_ARCHIVE_SAVE_AS is defined. +for ``YEAR_ARCHIVE_SAVE_AS`` is defined, each month if ``MONTH_ARCHIVE_SAVE_AS`` +is defined, and each day if ``DAY_ARCHIVE_SAVE_AS`` is defined. =================== =================================================== Variable Description @@ -313,8 +324,9 @@ period A tuple of the form (`year`, `month`, `day`) that =================== =================================================== -You can see an example of how to use `period` in the ``simple`` theme's -period_archives.html +You can see an example of how to use `period` in the `"simple" theme +`_. + Feeds ===== @@ -329,6 +341,8 @@ Here is a complete list of the feed variables:: FEED_ALL_RSS CATEGORY_FEED_ATOM CATEGORY_FEED_RSS + AUTHOR_FEED_ATOM + AUTHOR_FEED_RSS TAG_FEED_ATOM TAG_FEED_RSS TRANSLATION_FEED_ATOM @@ -346,7 +360,7 @@ missing, it will be replaced by the matching template from the ``simple`` theme. So if the HTML structure of a template in the ``simple`` theme is right for you, you don't have to write a new template from scratch. -You can also extend templates from the ``simple`` themes in your own themes by +You can also extend templates from the ``simple`` theme in your own themes by using the ``{% extends %}`` directive as in the following example: .. code-block:: html+jinja diff --git a/pelican/__init__.py b/pelican/__init__.py index 3080be37..967360c9 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -25,7 +25,7 @@ from pelican.settings import read_settings from pelican.utils import clean_output_dir, folder_watcher, file_watcher from pelican.writers import Writer -__version__ = "3.5.dev" +__version__ = "3.5.0" DEFAULT_CONFIG_NAME = 'pelicanconf.py' @@ -144,8 +144,10 @@ class Pelican(object): start_time = time.time() context = self.settings.copy() - context['filenames'] = {} # share the dict between all the generators - context['localsiteurl'] = self.settings['SITEURL'] # share + # Share these among all the generators and content objects: + context['filenames'] = {} # maps source path to Content object or None + context['localsiteurl'] = self.settings['SITEURL'] + generators = [ cls( context=context, @@ -157,7 +159,7 @@ class Pelican(object): ] # erase the directory if it is not the source and if that's - # explicitely asked + # explicitly asked if (self.delete_outputdir and not os.path.realpath(self.path).startswith(self.output_path)): clean_output_dir(self.output_path, self.output_retention) @@ -188,7 +190,7 @@ class Pelican(object): time.time() - start_time)) def get_generator_classes(self): - generators = [StaticGenerator, ArticlesGenerator, PagesGenerator] + generators = [ArticlesGenerator, PagesGenerator] if self.settings['TEMPLATE_PAGES']: generators.append(TemplatePagesGenerator) @@ -206,6 +208,10 @@ class Pelican(object): logger.debug('Found generator: %s', v) generators.append(v) + # StaticGenerator must run last, so it can identify files that + # were skipped by the other generators, and so static files can + # have their output paths overridden by the {attach} link syntax. + generators.append(StaticGenerator) return generators def get_writer(self): diff --git a/pelican/contents.py b/pelican/contents.py index 0249351c..1e31a57b 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -11,6 +11,7 @@ import os import re import sys +import pytz from pelican import signals from pelican.settings import DEFAULT_CONFIG @@ -132,8 +133,12 @@ class Content(object): # manage status if not hasattr(self, 'status'): self.status = settings['DEFAULT_STATUS'] - if not settings['WITH_FUTURE_DATES']: - if hasattr(self, 'date') and self.date > SafeDatetime.now(): + if not settings['WITH_FUTURE_DATES'] and hasattr(self, 'date'): + if self.date.tzinfo is None: + now = SafeDatetime.now() + else: + now = SafeDatetime.utcnow().replace(tzinfo=pytz.utc) + if self.date > now: self.status = 'draft' # store the summary metadata if it is set @@ -193,7 +198,7 @@ class Content(object): """Update the content attribute. Change all the relative paths of the content to relative paths - suitable for the ouput content. + suitable for the output content. :param content: content resource that will be passed to the templates. :param siteurl: siteurl which is locally generated by the writer in @@ -219,7 +224,7 @@ class Content(object): origin = m.group('path') # XXX Put this in a different location. - if what == 'filename': + if what in {'filename', 'attach'}: if path.startswith('/'): path = os.path.join(*path[1:].split('/')) else: @@ -234,9 +239,16 @@ class Content(object): if unquoted_path in self._context['filenames']: path = unquoted_path - if path in self._context['filenames']: - origin = '/'.join((siteurl, - self._context['filenames'][path].url)) + linked_content = self._context['filenames'].get(path) + if linked_content: + if what == 'attach': + if isinstance(linked_content, Static): + linked_content.attach_to(self) + else: + logger.warning("%s used {attach} link syntax on a " + "non-static file. Use {filename} instead.", + self.get_relative_source_path()) + origin = '/'.join((siteurl, linked_content.url)) origin = origin.replace('\\', '/') # for Windows paths. else: logger.warning( @@ -245,9 +257,9 @@ class Content(object): 'limit_msg': ("Other resources were not found " "and their urls not replaced")}) elif what == 'category': - origin = Category(path, self.settings).url + origin = '/'.join((siteurl, Category(path, self.settings).url)) elif what == 'tag': - origin = Tag(path, self.settings).url + origin = '/'.join((siteurl, Tag(path, self.settings).url)) # keep all other parts, such as query, fragment, etc. parts = list(value) @@ -261,16 +273,18 @@ class Content(object): @memoized def get_content(self, siteurl): - if hasattr(self, '_get_content'): content = self._get_content() else: content = self._content return self._update_content(content, siteurl) + def get_siteurl(self): + return self._context.get('localsiteurl', '') + @property def content(self): - return self.get_content(self._context.get('localsiteurl', '')) + return self.get_content(self.get_siteurl()) def _get_summary(self): """Returns the summary of an article. @@ -279,7 +293,8 @@ class Content(object): content. """ if hasattr(self, '_summary'): - return self._summary + return self._update_content(self._summary, + self.get_siteurl()) if self.settings['SUMMARY_MAX_LENGTH'] is None: return self.content @@ -287,12 +302,20 @@ class Content(object): return truncate_html_words(self.content, self.settings['SUMMARY_MAX_LENGTH']) - def _set_summary(self, summary): + @memoized + def get_summary(self, siteurl): + """uses siteurl to be memoizable""" + return self._get_summary() + + @property + def summary(self): + return self.get_summary(self.get_siteurl()) + + @summary.setter + def summary(self, value): """Dummy function""" pass - summary = property(_get_summary, _set_summary, "Summary of the article." - "Based on the content. Can't be set") url = property(functools.partial(get_url_setting, key='url')) save_as = property(functools.partial(get_url_setting, key='save_as')) @@ -348,6 +371,10 @@ class Quote(Page): @python_2_unicode_compatible class Static(Page): + def __init__(self, *args, **kwargs): + super(Static, self).__init__(*args, **kwargs) + self._output_location_referenced = False + @deprecated_attribute(old='filepath', new='source_path', since=(3, 2, 0)) def filepath(): return None @@ -360,6 +387,65 @@ class Static(Page): def dst(): return None + @property + def url(self): + # Note when url has been referenced, so we can avoid overriding it. + self._output_location_referenced = True + return super(Static, self).url + + @property + def save_as(self): + # Note when save_as has been referenced, so we can avoid overriding it. + self._output_location_referenced = True + return super(Static, self).save_as + + def attach_to(self, content): + """Override our output directory with that of the given content object. + """ + # Determine our file's new output path relative to the linking document. + # If it currently lives beneath the linking document's source directory, + # preserve that relationship on output. Otherwise, make it a sibling. + linking_source_dir = os.path.dirname(content.source_path) + tail_path = os.path.relpath(self.source_path, linking_source_dir) + if tail_path.startswith(os.pardir + os.sep): + tail_path = os.path.basename(tail_path) + new_save_as = os.path.join( + os.path.dirname(content.save_as), tail_path) + + # We do not build our new url by joining tail_path with the linking + # document's url, because we cannot know just by looking at the latter + # whether it points to the document itself or to its parent directory. + # (An url like 'some/content' might mean a directory named 'some' + # with a file named 'content', or it might mean a directory named + # 'some/content' with a file named 'index.html'.) Rather than trying + # to figure it out by comparing the linking document's url and save_as + # path, we simply build our new url from our new save_as path. + new_url = path_to_url(new_save_as) + + def _log_reason(reason): + logger.warning("The {attach} link in %s cannot relocate %s " + "because %s. Falling back to {filename} link behavior instead.", + content.get_relative_source_path(), + self.get_relative_source_path(), reason, + extra={'limit_msg': "More {attach} warnings silenced."}) + + # We never override an override, because we don't want to interfere + # with user-defined overrides that might be in EXTRA_PATH_METADATA. + if hasattr(self, 'override_save_as') or hasattr(self, 'override_url'): + if new_save_as != self.save_as or new_url != self.url: + _log_reason("its output location was already overridden") + return + + # We never change an output path that has already been referenced, + # because we don't want to break links that depend on that path. + if self._output_location_referenced: + if new_save_as != self.save_as or new_url != self.url: + _log_reason("another link already referenced its location") + return + + self.override_save_as = new_save_as + self.override_url = new_url + def is_valid_content(content, f): try: diff --git a/pelican/generators.py b/pelican/generators.py index 07945f13..5122fa6d 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -122,13 +122,21 @@ class Generator(object): """ if isinstance(paths, six.string_types): paths = [paths] # backward compatibility for older generators + + # group the exclude dir names by parent path, for use with os.walk() + exclusions_by_dirpath = {} + for e in exclude: + parent_path, subdir = os.path.split(os.path.join(self.path, e)) + exclusions_by_dirpath.setdefault(parent_path, set()).add(subdir) + files = [] for path in paths: - root = os.path.join(self.path, path) + # careful: os.path.join() will add a slash when path == ''. + root = os.path.join(self.path, path) if path else self.path if os.path.isdir(root): for dirpath, dirs, temp_files in os.walk(root, followlinks=True): - for e in exclude: + for e in exclusions_by_dirpath.get(dirpath, ()): if e in dirs: dirs.remove(e) reldir = os.path.relpath(dirpath, self.path) @@ -141,9 +149,27 @@ class Generator(object): return files def add_source_path(self, content): + """Record a source file path that a Generator found and processed. + Store a reference to its Content object, for url lookups later. + """ location = content.get_relative_source_path() self.context['filenames'][location] = content + def _add_failed_source_path(self, path): + """Record a source file path that a Generator failed to process. + (For example, one that was missing mandatory metadata.) + The path argument is expected to be relative to self.path. + """ + self.context['filenames'][os.path.normpath(path)] = None + + def _is_potential_source_path(self, path): + """Return True if path was supposed to be used as a source file. + (This includes all source files that have been found by generators + before this method is called, even if they failed to process.) + The path argument is expected to be relative to self.path. + """ + return os.path.normpath(path) in self.context['filenames'] + def _update_context(self, items): """Update the context with the given items from the currrent processor. @@ -477,9 +503,11 @@ class ArticlesGenerator(CachingGenerator): except Exception as e: logger.error('Could not process %s\n%s', f, e, exc_info=self.settings.get('DEBUG', False)) + self._add_failed_source_path(f) continue if not is_valid_content(article, f): + self._add_failed_source_path(f) continue self.cache_data(f, article) @@ -602,9 +630,11 @@ class PagesGenerator(CachingGenerator): except Exception as e: logger.error('Could not process %s\n%s', f, e, exc_info=self.settings.get('DEBUG', False)) + self._add_failed_source_path(f) continue if not is_valid_content(page, f): + self._add_failed_source_path(f) continue self.cache_data(f, page) @@ -663,7 +693,14 @@ class StaticGenerator(Generator): def generate_context(self): self.staticfiles = [] for f in self.get_files(self.settings['STATIC_PATHS'], + exclude=self.settings['STATIC_EXCLUDES'], extensions=False): + + # skip content source files unless the user explicitly wants them + if self.settings['STATIC_EXCLUDE_SOURCES']: + if self._is_potential_source_path(f): + continue + static = self.readers.read_file( base_path=self.path, path=f, content_class=Static, fmt='static', context=self.context, diff --git a/pelican/log.py b/pelican/log.py index 089bc0ac..cd750927 100644 --- a/pelican/log.py +++ b/pelican/log.py @@ -33,7 +33,7 @@ class BaseFormatter(logging.Formatter): s = super(BaseFormatter, self).formatException(ei) # fancy format traceback s = str('\n').join(str(' | ') + line for line in s.splitlines()) - # seperate the traceback from the preceding lines + # separate the traceback from the preceding lines s = str(' |___\n{}').format(s) return s diff --git a/pelican/rstdirectives.py b/pelican/rstdirectives.py index 1bf6971c..1c25cc42 100644 --- a/pelican/rstdirectives.py +++ b/pelican/rstdirectives.py @@ -70,7 +70,7 @@ directives.register_directive('code-block', Pygments) directives.register_directive('sourcecode', Pygments) -_abbr_re = re.compile('\((.*)\)$') +_abbr_re = re.compile('\((.*)\)$', re.DOTALL) class abbreviation(nodes.Inline, nodes.TextElement): diff --git a/pelican/settings.py b/pelican/settings.py index 631c6d24..794733d7 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -36,7 +36,9 @@ DEFAULT_CONFIG = { 'THEME': DEFAULT_THEME, 'OUTPUT_PATH': 'output', 'READERS': {}, - 'STATIC_PATHS': ['images', ], + 'STATIC_PATHS': ['images'], + 'STATIC_EXCLUDES': [], + 'STATIC_EXCLUDE_SOURCES': True, 'THEME_STATIC_DIR': 'theme', 'THEME_STATIC_PATHS': ['static', ], 'FEED_ALL_ATOM': os.path.join('feeds', 'all.atom.xml'), @@ -339,6 +341,7 @@ def configure_settings(settings): 'JINJA_EXTENSIONS', 'PAGINATED_DIRECT_TEMPLATES', 'PLUGINS', + 'STATIC_EXCLUDES', 'STATIC_PATHS', 'THEME_STATIC_PATHS', 'ARTICLE_PATHS', diff --git a/pelican/tests/TestPages/page_with_category_and_tag_links.md b/pelican/tests/TestPages/page_with_category_and_tag_links.md new file mode 100644 index 00000000..6806a570 --- /dev/null +++ b/pelican/tests/TestPages/page_with_category_and_tag_links.md @@ -0,0 +1,7 @@ +Title: Page with a bunch of links + +My links: + +[Link 1]({tag}マック) + +[Link 2]({category}Yeah) diff --git a/pelican/tests/mixed_content/fake_image.jpg b/pelican/tests/mixed_content/fake_image.jpg new file mode 100644 index 00000000..e69de29b diff --git a/pelican/tests/mixed_content/short_page.md b/pelican/tests/mixed_content/short_page.md new file mode 100644 index 00000000..46ca45ac --- /dev/null +++ b/pelican/tests/mixed_content/short_page.md @@ -0,0 +1,3 @@ +Title: Short Page + +This is a page with little text. diff --git a/pelican/tests/mixed_content/subdir/subdir_fake_image.jpg b/pelican/tests/mixed_content/subdir/subdir_fake_image.jpg new file mode 100644 index 00000000..e69de29b diff --git a/pelican/tests/nested_content/maindir/maindir.md b/pelican/tests/nested_content/maindir/maindir.md new file mode 100644 index 00000000..443e1827 --- /dev/null +++ b/pelican/tests/nested_content/maindir/maindir.md @@ -0,0 +1,3 @@ +Title: Main Dir Page + +This page lives in maindir. diff --git a/pelican/tests/nested_content/maindir/subdir/subdir.md b/pelican/tests/nested_content/maindir/subdir/subdir.md new file mode 100644 index 00000000..32e73617 --- /dev/null +++ b/pelican/tests/nested_content/maindir/subdir/subdir.md @@ -0,0 +1,3 @@ +Title: Subdir Page + +This page lives in maindir/subdir. diff --git a/pelican/tests/output/custom_locale/feeds/alexis-metaireau.atom.xml b/pelican/tests/output/custom_locale/feeds/alexis-metaireau.atom.xml index 202b9f71..8fb3ef64 100644 --- a/pelican/tests/output/custom_locale/feeds/alexis-metaireau.atom.xml +++ b/pelican/tests/output/custom_locale/feeds/alexis-metaireau.atom.xml @@ -1,12 +1,12 @@ -Alexis' loghttp://blog.notmyidea.org/2013-11-17T23:29:00+01:00FILENAME_METADATA example2012-11-30T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-11-30:posts/2012/November/30/filename_metadata-example/<p>Some cool stuff!</p> -Second article2012-02-29T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-02-29:posts/2012/February/29/second-article/<p>This is some article, in english</p> -A markdown powered article2011-04-20T00:00:00+02:00Alexis Métaireautag:blog.notmyidea.org,2011-04-20:posts/2011/April/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> -<p><a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a root-relative link to unbelievable</a> -<a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a file-relative link to unbelievable</a></p>Article 12011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-1/<p>Article 1</p> -Article 22011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-2/<p>Article 2</p> -Article 32011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-3/<p>Article 3</p> -This is a super article !2013-11-17T23:29:00+01:00Alexis Métaireautag:blog.notmyidea.org,2010-12-02:posts/2010/December/02/this-is-a-super-article/<p>Some content here !</p> +Alexis' loghttp://blog.notmyidea.org/2013-11-17T23:29:00+01:00FILENAME_METADATA example2012-11-30T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-11-30:posts/2012/novembre/30/filename_metadata-example/<p>Some cool stuff!</p> +Second article2012-02-29T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-02-29:posts/2012/février/29/second-article/<p>This is some article, in english</p> +A markdown powered article2011-04-20T00:00:00+02:00Alexis Métaireautag:blog.notmyidea.org,2011-04-20:posts/2011/avril/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> +<p><a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a root-relative link to unbelievable</a> +<a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a file-relative link to unbelievable</a></p>Article 12011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-1/<p>Article 1</p> +Article 22011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-2/<p>Article 2</p> +Article 32011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-3/<p>Article 3</p> +This is a super article !2013-11-17T23:29:00+01:00Alexis Métaireautag:blog.notmyidea.org,2010-12-02:posts/2010/décembre/02/this-is-a-super-article/<p>Some content here !</p> <div class="section" id="this-is-a-simple-title"> <h2>This is a simple title</h2> <p>And here comes the cool <a class="reference external" href="http://books.couchdb.org/relax/design-documents/views">stuff</a>.</p> @@ -18,15 +18,15 @@ </pre> <p>→ And now try with some utf8 hell: ééé</p> </div> -Oh yeah !2010-10-20T10:14:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-20:posts/2010/October/20/oh-yeah/<div class="section" id="why-not"> +Oh yeah !2010-10-20T10:14:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-20:posts/2010/octobre/20/oh-yeah/<div class="section" id="why-not"> <h2>Why not ?</h2> <p>After all, why not ? It's pretty simple to do it, and it will allow me to write my blogposts in rst ! YEAH !</p> <img alt="alternate text" src="http://blog.notmyidea.org/pictures/Sushi.jpg" style="width: 600px; height: 450px;" /> </div> -Unbelievable !2010-10-15T20:30:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-15:posts/2010/October/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> -<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> -<a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> +Unbelievable !2010-10-15T20:30:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-15:posts/2010/octobre/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> +<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> +<a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> <div class="section" id="testing-sourcecode-directive"> <h2>Testing sourcecode directive</h2> <table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span class="n">formatter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="ow">and</span> <span class="n">VARIANTS</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]]</span> diff --git a/pelican/tests/output/custom_locale/feeds/alexis-metaireau.rss.xml b/pelican/tests/output/custom_locale/feeds/alexis-metaireau.rss.xml index dfb83630..99255ee5 100644 --- a/pelican/tests/output/custom_locale/feeds/alexis-metaireau.rss.xml +++ b/pelican/tests/output/custom_locale/feeds/alexis-metaireau.rss.xml @@ -1,12 +1,12 @@ -Alexis' loghttp://blog.notmyidea.org/Sun, 17 Nov 2013 23:29:00 +0100FILENAME_METADATA examplehttp://blog.notmyidea.org/posts/2012/November/30/filename_metadata-example/<p>Some cool stuff!</p> -Alexis MétaireauFri, 30 Nov 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-11-30:posts/2012/November/30/filename_metadata-example/Second articlehttp://blog.notmyidea.org/posts/2012/February/29/second-article/<p>This is some article, in english</p> -Alexis MétaireauWed, 29 Feb 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-02-29:posts/2012/February/29/second-article/foobarbazA markdown powered articlehttp://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> -<p><a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a root-relative link to unbelievable</a> -<a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a file-relative link to unbelievable</a></p>Alexis MétaireauWed, 20 Apr 2011 00:00:00 +0200tag:blog.notmyidea.org,2011-04-20:posts/2011/April/20/a-markdown-powered-article/Article 1http://blog.notmyidea.org/posts/2011/February/17/article-1/<p>Article 1</p> -Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-1/Article 2http://blog.notmyidea.org/posts/2011/February/17/article-2/<p>Article 2</p> -Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-2/Article 3http://blog.notmyidea.org/posts/2011/February/17/article-3/<p>Article 3</p> -Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-3/This is a super article !http://blog.notmyidea.org/posts/2010/December/02/this-is-a-super-article/<p>Some content here !</p> +Alexis' loghttp://blog.notmyidea.org/Sun, 17 Nov 2013 23:29:00 +0100FILENAME_METADATA examplehttp://blog.notmyidea.org/posts/2012/novembre/30/filename_metadata-example/<p>Some cool stuff!</p> +Alexis MétaireauFri, 30 Nov 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-11-30:posts/2012/novembre/30/filename_metadata-example/Second articlehttp://blog.notmyidea.org/posts/2012/f%C3%A9vrier/29/second-article/<p>This is some article, in english</p> +Alexis MétaireauWed, 29 Feb 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-02-29:posts/2012/février/29/second-article/foobarbazA markdown powered articlehttp://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> +<p><a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a root-relative link to unbelievable</a> +<a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a file-relative link to unbelievable</a></p>Alexis MétaireauWed, 20 Apr 2011 00:00:00 +0200tag:blog.notmyidea.org,2011-04-20:posts/2011/avril/20/a-markdown-powered-article/Article 1http://blog.notmyidea.org/posts/2011/f%C3%A9vrier/17/article-1/<p>Article 1</p> +Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-1/Article 2http://blog.notmyidea.org/posts/2011/f%C3%A9vrier/17/article-2/<p>Article 2</p> +Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-2/Article 3http://blog.notmyidea.org/posts/2011/f%C3%A9vrier/17/article-3/<p>Article 3</p> +Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-3/This is a super article !http://blog.notmyidea.org/posts/2010/d%C3%A9cembre/02/this-is-a-super-article/<p>Some content here !</p> <div class="section" id="this-is-a-simple-title"> <h2>This is a simple title</h2> <p>And here comes the cool <a class="reference external" href="http://books.couchdb.org/relax/design-documents/views">stuff</a>.</p> @@ -18,15 +18,15 @@ </pre> <p>→ And now try with some utf8 hell: ééé</p> </div> -Alexis MétaireauSun, 17 Nov 2013 23:29:00 +0100tag:blog.notmyidea.org,2010-12-02:posts/2010/December/02/this-is-a-super-article/foobarfoobarOh yeah !http://blog.notmyidea.org/posts/2010/October/20/oh-yeah/<div class="section" id="why-not"> +Alexis MétaireauSun, 17 Nov 2013 23:29:00 +0100tag:blog.notmyidea.org,2010-12-02:posts/2010/décembre/02/this-is-a-super-article/foobarfoobarOh yeah !http://blog.notmyidea.org/posts/2010/octobre/20/oh-yeah/<div class="section" id="why-not"> <h2>Why not ?</h2> <p>After all, why not ? It's pretty simple to do it, and it will allow me to write my blogposts in rst ! YEAH !</p> <img alt="alternate text" src="http://blog.notmyidea.org/pictures/Sushi.jpg" style="width: 600px; height: 450px;" /> </div> -Alexis MétaireauWed, 20 Oct 2010 10:14:00 +0200tag:blog.notmyidea.org,2010-10-20:posts/2010/October/20/oh-yeah/ohbaryeahUnbelievable !http://blog.notmyidea.org/posts/2010/October/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> -<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> -<a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> +Alexis MétaireauWed, 20 Oct 2010 10:14:00 +0200tag:blog.notmyidea.org,2010-10-20:posts/2010/octobre/20/oh-yeah/ohbaryeahUnbelievable !http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> +<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> +<a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> <div class="section" id="testing-sourcecode-directive"> <h2>Testing sourcecode directive</h2> <table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span class="n">formatter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="ow">and</span> <span class="n">VARIANTS</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]]</span> @@ -57,5 +57,5 @@ pelican.conf, it will have nothing in default.</p> </pre></div> <p>Lovely.</p> </div> -Alexis MétaireauFri, 15 Oct 2010 20:30:00 +0200tag:blog.notmyidea.org,2010-10-15:posts/2010/October/15/unbelievable/The baz taghttp://blog.notmyidea.org/tag/baz.html<p>This article overrides the listening of the articles under the <em>baz</em> tag.</p> +Alexis MétaireauFri, 15 Oct 2010 20:30:00 +0200tag:blog.notmyidea.org,2010-10-15:posts/2010/octobre/15/unbelievable/The baz taghttp://blog.notmyidea.org/tag/baz.html<p>This article overrides the listening of the articles under the <em>baz</em> tag.</p> Alexis MétaireauSun, 14 Mar 2010 00:00:00 +0100tag:blog.notmyidea.org,2010-03-14:tag/baz.html \ No newline at end of file diff --git a/pelican/tests/output/custom_locale/feeds/all-en.atom.xml b/pelican/tests/output/custom_locale/feeds/all-en.atom.xml index 3bb10e38..6b2f09ba 100644 --- a/pelican/tests/output/custom_locale/feeds/all-en.atom.xml +++ b/pelican/tests/output/custom_locale/feeds/all-en.atom.xml @@ -1,12 +1,12 @@ -Alexis' loghttp://blog.notmyidea.org/2013-11-17T23:29:00+01:00FILENAME_METADATA example2012-11-30T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-11-30:posts/2012/November/30/filename_metadata-example/<p>Some cool stuff!</p> -Second article2012-02-29T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-02-29:posts/2012/February/29/second-article/<p>This is some article, in english</p> -A markdown powered article2011-04-20T00:00:00+02:00Alexis Métaireautag:blog.notmyidea.org,2011-04-20:posts/2011/April/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> -<p><a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a root-relative link to unbelievable</a> -<a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a file-relative link to unbelievable</a></p>Article 12011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-1/<p>Article 1</p> -Article 22011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-2/<p>Article 2</p> -Article 32011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-3/<p>Article 3</p> -This is a super article !2013-11-17T23:29:00+01:00Alexis Métaireautag:blog.notmyidea.org,2010-12-02:posts/2010/December/02/this-is-a-super-article/<p>Some content here !</p> +Alexis' loghttp://blog.notmyidea.org/2013-11-17T23:29:00+01:00FILENAME_METADATA example2012-11-30T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-11-30:posts/2012/novembre/30/filename_metadata-example/<p>Some cool stuff!</p> +Second article2012-02-29T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-02-29:posts/2012/février/29/second-article/<p>This is some article, in english</p> +A markdown powered article2011-04-20T00:00:00+02:00Alexis Métaireautag:blog.notmyidea.org,2011-04-20:posts/2011/avril/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> +<p><a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a root-relative link to unbelievable</a> +<a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a file-relative link to unbelievable</a></p>Article 12011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-1/<p>Article 1</p> +Article 22011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-2/<p>Article 2</p> +Article 32011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-3/<p>Article 3</p> +This is a super article !2013-11-17T23:29:00+01:00Alexis Métaireautag:blog.notmyidea.org,2010-12-02:posts/2010/décembre/02/this-is-a-super-article/<p>Some content here !</p> <div class="section" id="this-is-a-simple-title"> <h2>This is a simple title</h2> <p>And here comes the cool <a class="reference external" href="http://books.couchdb.org/relax/design-documents/views">stuff</a>.</p> @@ -18,15 +18,15 @@ </pre> <p>→ And now try with some utf8 hell: ééé</p> </div> -Oh yeah !2010-10-20T10:14:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-20:posts/2010/October/20/oh-yeah/<div class="section" id="why-not"> +Oh yeah !2010-10-20T10:14:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-20:posts/2010/octobre/20/oh-yeah/<div class="section" id="why-not"> <h2>Why not ?</h2> <p>After all, why not ? It's pretty simple to do it, and it will allow me to write my blogposts in rst ! YEAH !</p> <img alt="alternate text" src="http://blog.notmyidea.org/pictures/Sushi.jpg" style="width: 600px; height: 450px;" /> </div> -Unbelievable !2010-10-15T20:30:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-15:posts/2010/October/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> -<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> -<a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> +Unbelievable !2010-10-15T20:30:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-15:posts/2010/octobre/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> +<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> +<a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> <div class="section" id="testing-sourcecode-directive"> <h2>Testing sourcecode directive</h2> <table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span class="n">formatter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="ow">and</span> <span class="n">VARIANTS</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]]</span> diff --git a/pelican/tests/output/custom_locale/feeds/all.atom.xml b/pelican/tests/output/custom_locale/feeds/all.atom.xml index f709f2b1..5ef59e04 100644 --- a/pelican/tests/output/custom_locale/feeds/all.atom.xml +++ b/pelican/tests/output/custom_locale/feeds/all.atom.xml @@ -1,14 +1,14 @@ -Alexis' loghttp://blog.notmyidea.org/2013-11-17T23:29:00+01:00FILENAME_METADATA example2012-11-30T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-11-30:posts/2012/November/30/filename_metadata-example/<p>Some cool stuff!</p> +Alexis' loghttp://blog.notmyidea.org/2013-11-17T23:29:00+01:00FILENAME_METADATA example2012-11-30T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-11-30:posts/2012/novembre/30/filename_metadata-example/<p>Some cool stuff!</p> Trop bien !2012-03-02T14:01:01+01:00Alexis Métaireautag:blog.notmyidea.org,2012-03-02:oh-yeah-fr.html<p>Et voila du contenu en français</p> -Second article2012-02-29T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-02-29:posts/2012/February/29/second-article/<p>This is some article, in english</p> +Second article2012-02-29T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-02-29:posts/2012/février/29/second-article/<p>This is some article, in english</p> Deuxième article2012-02-29T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-02-29:second-article-fr.html<p>Ceci est un article, en français.</p> -A markdown powered article2011-04-20T00:00:00+02:00Alexis Métaireautag:blog.notmyidea.org,2011-04-20:posts/2011/April/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> -<p><a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a root-relative link to unbelievable</a> -<a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a file-relative link to unbelievable</a></p>Article 12011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-1/<p>Article 1</p> -Article 22011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-2/<p>Article 2</p> -Article 32011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-3/<p>Article 3</p> -This is a super article !2013-11-17T23:29:00+01:00Alexis Métaireautag:blog.notmyidea.org,2010-12-02:posts/2010/December/02/this-is-a-super-article/<p>Some content here !</p> +A markdown powered article2011-04-20T00:00:00+02:00Alexis Métaireautag:blog.notmyidea.org,2011-04-20:posts/2011/avril/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> +<p><a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a root-relative link to unbelievable</a> +<a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a file-relative link to unbelievable</a></p>Article 12011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-1/<p>Article 1</p> +Article 22011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-2/<p>Article 2</p> +Article 32011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-3/<p>Article 3</p> +This is a super article !2013-11-17T23:29:00+01:00Alexis Métaireautag:blog.notmyidea.org,2010-12-02:posts/2010/décembre/02/this-is-a-super-article/<p>Some content here !</p> <div class="section" id="this-is-a-simple-title"> <h2>This is a simple title</h2> <p>And here comes the cool <a class="reference external" href="http://books.couchdb.org/relax/design-documents/views">stuff</a>.</p> @@ -20,15 +20,15 @@ </pre> <p>→ And now try with some utf8 hell: ééé</p> </div> -Oh yeah !2010-10-20T10:14:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-20:posts/2010/October/20/oh-yeah/<div class="section" id="why-not"> +Oh yeah !2010-10-20T10:14:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-20:posts/2010/octobre/20/oh-yeah/<div class="section" id="why-not"> <h2>Why not ?</h2> <p>After all, why not ? It's pretty simple to do it, and it will allow me to write my blogposts in rst ! YEAH !</p> <img alt="alternate text" src="http://blog.notmyidea.org/pictures/Sushi.jpg" style="width: 600px; height: 450px;" /> </div> -Unbelievable !2010-10-15T20:30:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-15:posts/2010/October/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> -<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> -<a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> +Unbelievable !2010-10-15T20:30:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-15:posts/2010/octobre/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> +<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> +<a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> <div class="section" id="testing-sourcecode-directive"> <h2>Testing sourcecode directive</h2> <table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span class="n">formatter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="ow">and</span> <span class="n">VARIANTS</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]]</span> diff --git a/pelican/tests/output/custom_locale/feeds/all.rss.xml b/pelican/tests/output/custom_locale/feeds/all.rss.xml index 39fbc240..071e2f1a 100644 --- a/pelican/tests/output/custom_locale/feeds/all.rss.xml +++ b/pelican/tests/output/custom_locale/feeds/all.rss.xml @@ -1,14 +1,14 @@ -Alexis' loghttp://blog.notmyidea.org/Sun, 17 Nov 2013 23:29:00 +0100FILENAME_METADATA examplehttp://blog.notmyidea.org/posts/2012/November/30/filename_metadata-example/<p>Some cool stuff!</p> -Alexis MétaireauFri, 30 Nov 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-11-30:posts/2012/November/30/filename_metadata-example/Trop bien !http://blog.notmyidea.org/oh-yeah-fr.html<p>Et voila du contenu en français</p> -Alexis MétaireauFri, 02 Mar 2012 14:01:01 +0100tag:blog.notmyidea.org,2012-03-02:oh-yeah-fr.htmlSecond articlehttp://blog.notmyidea.org/posts/2012/February/29/second-article/<p>This is some article, in english</p> -Alexis MétaireauWed, 29 Feb 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-02-29:posts/2012/February/29/second-article/foobarbazDeuxième articlehttp://blog.notmyidea.org/second-article-fr.html<p>Ceci est un article, en français.</p> -Alexis MétaireauWed, 29 Feb 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-02-29:second-article-fr.htmlfoobarbazA markdown powered articlehttp://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> -<p><a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a root-relative link to unbelievable</a> -<a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a file-relative link to unbelievable</a></p>Alexis MétaireauWed, 20 Apr 2011 00:00:00 +0200tag:blog.notmyidea.org,2011-04-20:posts/2011/April/20/a-markdown-powered-article/Article 1http://blog.notmyidea.org/posts/2011/February/17/article-1/<p>Article 1</p> -Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-1/Article 2http://blog.notmyidea.org/posts/2011/February/17/article-2/<p>Article 2</p> -Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-2/Article 3http://blog.notmyidea.org/posts/2011/February/17/article-3/<p>Article 3</p> -Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-3/This is a super article !http://blog.notmyidea.org/posts/2010/December/02/this-is-a-super-article/<p>Some content here !</p> +Alexis' loghttp://blog.notmyidea.org/Sun, 17 Nov 2013 23:29:00 +0100FILENAME_METADATA examplehttp://blog.notmyidea.org/posts/2012/novembre/30/filename_metadata-example/<p>Some cool stuff!</p> +Alexis MétaireauFri, 30 Nov 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-11-30:posts/2012/novembre/30/filename_metadata-example/Trop bien !http://blog.notmyidea.org/oh-yeah-fr.html<p>Et voila du contenu en français</p> +Alexis MétaireauFri, 02 Mar 2012 14:01:01 +0100tag:blog.notmyidea.org,2012-03-02:oh-yeah-fr.htmlSecond articlehttp://blog.notmyidea.org/posts/2012/f%C3%A9vrier/29/second-article/<p>This is some article, in english</p> +Alexis MétaireauWed, 29 Feb 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-02-29:posts/2012/février/29/second-article/foobarbazDeuxième articlehttp://blog.notmyidea.org/second-article-fr.html<p>Ceci est un article, en français.</p> +Alexis MétaireauWed, 29 Feb 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-02-29:second-article-fr.htmlfoobarbazA markdown powered articlehttp://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> +<p><a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a root-relative link to unbelievable</a> +<a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a file-relative link to unbelievable</a></p>Alexis MétaireauWed, 20 Apr 2011 00:00:00 +0200tag:blog.notmyidea.org,2011-04-20:posts/2011/avril/20/a-markdown-powered-article/Article 1http://blog.notmyidea.org/posts/2011/f%C3%A9vrier/17/article-1/<p>Article 1</p> +Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-1/Article 2http://blog.notmyidea.org/posts/2011/f%C3%A9vrier/17/article-2/<p>Article 2</p> +Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-2/Article 3http://blog.notmyidea.org/posts/2011/f%C3%A9vrier/17/article-3/<p>Article 3</p> +Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-3/This is a super article !http://blog.notmyidea.org/posts/2010/d%C3%A9cembre/02/this-is-a-super-article/<p>Some content here !</p> <div class="section" id="this-is-a-simple-title"> <h2>This is a simple title</h2> <p>And here comes the cool <a class="reference external" href="http://books.couchdb.org/relax/design-documents/views">stuff</a>.</p> @@ -20,15 +20,15 @@ </pre> <p>→ And now try with some utf8 hell: ééé</p> </div> -Alexis MétaireauSun, 17 Nov 2013 23:29:00 +0100tag:blog.notmyidea.org,2010-12-02:posts/2010/December/02/this-is-a-super-article/foobarfoobarOh yeah !http://blog.notmyidea.org/posts/2010/October/20/oh-yeah/<div class="section" id="why-not"> +Alexis MétaireauSun, 17 Nov 2013 23:29:00 +0100tag:blog.notmyidea.org,2010-12-02:posts/2010/décembre/02/this-is-a-super-article/foobarfoobarOh yeah !http://blog.notmyidea.org/posts/2010/octobre/20/oh-yeah/<div class="section" id="why-not"> <h2>Why not ?</h2> <p>After all, why not ? It's pretty simple to do it, and it will allow me to write my blogposts in rst ! YEAH !</p> <img alt="alternate text" src="http://blog.notmyidea.org/pictures/Sushi.jpg" style="width: 600px; height: 450px;" /> </div> -Alexis MétaireauWed, 20 Oct 2010 10:14:00 +0200tag:blog.notmyidea.org,2010-10-20:posts/2010/October/20/oh-yeah/ohbaryeahUnbelievable !http://blog.notmyidea.org/posts/2010/October/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> -<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> -<a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> +Alexis MétaireauWed, 20 Oct 2010 10:14:00 +0200tag:blog.notmyidea.org,2010-10-20:posts/2010/octobre/20/oh-yeah/ohbaryeahUnbelievable !http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> +<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> +<a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> <div class="section" id="testing-sourcecode-directive"> <h2>Testing sourcecode directive</h2> <table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span class="n">formatter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="ow">and</span> <span class="n">VARIANTS</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]]</span> @@ -59,5 +59,5 @@ pelican.conf, it will have nothing in default.</p> </pre></div> <p>Lovely.</p> </div> -Alexis MétaireauFri, 15 Oct 2010 20:30:00 +0200tag:blog.notmyidea.org,2010-10-15:posts/2010/October/15/unbelievable/The baz taghttp://blog.notmyidea.org/tag/baz.html<p>This article overrides the listening of the articles under the <em>baz</em> tag.</p> +Alexis MétaireauFri, 15 Oct 2010 20:30:00 +0200tag:blog.notmyidea.org,2010-10-15:posts/2010/octobre/15/unbelievable/The baz taghttp://blog.notmyidea.org/tag/baz.html<p>This article overrides the listening of the articles under the <em>baz</em> tag.</p> Alexis MétaireauSun, 14 Mar 2010 00:00:00 +0100tag:blog.notmyidea.org,2010-03-14:tag/baz.html \ No newline at end of file diff --git a/pelican/tests/output/custom_locale/feeds/bar.atom.xml b/pelican/tests/output/custom_locale/feeds/bar.atom.xml index 13a5cde2..02fae916 100644 --- a/pelican/tests/output/custom_locale/feeds/bar.atom.xml +++ b/pelican/tests/output/custom_locale/feeds/bar.atom.xml @@ -1,5 +1,5 @@ -Alexis' loghttp://blog.notmyidea.org/2010-10-20T10:14:00+02:00Oh yeah !2010-10-20T10:14:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-20:posts/2010/October/20/oh-yeah/<div class="section" id="why-not"> +Alexis' loghttp://blog.notmyidea.org/2010-10-20T10:14:00+02:00Oh yeah !2010-10-20T10:14:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-20:posts/2010/octobre/20/oh-yeah/<div class="section" id="why-not"> <h2>Why not ?</h2> <p>After all, why not ? It's pretty simple to do it, and it will allow me to write my blogposts in rst ! YEAH !</p> diff --git a/pelican/tests/output/custom_locale/feeds/bar.rss.xml b/pelican/tests/output/custom_locale/feeds/bar.rss.xml index 4426eb6a..96074958 100644 --- a/pelican/tests/output/custom_locale/feeds/bar.rss.xml +++ b/pelican/tests/output/custom_locale/feeds/bar.rss.xml @@ -1,8 +1,8 @@ -Alexis' loghttp://blog.notmyidea.org/Wed, 20 Oct 2010 10:14:00 +0200Oh yeah !http://blog.notmyidea.org/posts/2010/October/20/oh-yeah/<div class="section" id="why-not"> +Alexis' loghttp://blog.notmyidea.org/Wed, 20 Oct 2010 10:14:00 +0200Oh yeah !http://blog.notmyidea.org/posts/2010/octobre/20/oh-yeah/<div class="section" id="why-not"> <h2>Why not ?</h2> <p>After all, why not ? It's pretty simple to do it, and it will allow me to write my blogposts in rst ! YEAH !</p> <img alt="alternate text" src="http://blog.notmyidea.org/pictures/Sushi.jpg" style="width: 600px; height: 450px;" /> </div> -Alexis MétaireauWed, 20 Oct 2010 10:14:00 +0200tag:blog.notmyidea.org,2010-10-20:posts/2010/October/20/oh-yeah/ohbaryeah \ No newline at end of file +Alexis MétaireauWed, 20 Oct 2010 10:14:00 +0200tag:blog.notmyidea.org,2010-10-20:posts/2010/octobre/20/oh-yeah/ohbaryeah \ No newline at end of file diff --git a/pelican/tests/output/custom_locale/feeds/cat1.atom.xml b/pelican/tests/output/custom_locale/feeds/cat1.atom.xml index 54d382c4..96f70900 100644 --- a/pelican/tests/output/custom_locale/feeds/cat1.atom.xml +++ b/pelican/tests/output/custom_locale/feeds/cat1.atom.xml @@ -1,7 +1,7 @@ -Alexis' loghttp://blog.notmyidea.org/2011-04-20T00:00:00+02:00A markdown powered article2011-04-20T00:00:00+02:00Alexis Métaireautag:blog.notmyidea.org,2011-04-20:posts/2011/April/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> -<p><a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a root-relative link to unbelievable</a> -<a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a file-relative link to unbelievable</a></p>Article 12011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-1/<p>Article 1</p> -Article 22011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-2/<p>Article 2</p> -Article 32011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-3/<p>Article 3</p> +Alexis' loghttp://blog.notmyidea.org/2011-04-20T00:00:00+02:00A markdown powered article2011-04-20T00:00:00+02:00Alexis Métaireautag:blog.notmyidea.org,2011-04-20:posts/2011/avril/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> +<p><a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a root-relative link to unbelievable</a> +<a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a file-relative link to unbelievable</a></p>Article 12011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-1/<p>Article 1</p> +Article 22011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-2/<p>Article 2</p> +Article 32011-02-17T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-3/<p>Article 3</p> \ No newline at end of file diff --git a/pelican/tests/output/custom_locale/feeds/cat1.rss.xml b/pelican/tests/output/custom_locale/feeds/cat1.rss.xml index 4f3b12f5..b78f51cc 100644 --- a/pelican/tests/output/custom_locale/feeds/cat1.rss.xml +++ b/pelican/tests/output/custom_locale/feeds/cat1.rss.xml @@ -1,7 +1,7 @@ -Alexis' loghttp://blog.notmyidea.org/Wed, 20 Apr 2011 00:00:00 +0200A markdown powered articlehttp://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> -<p><a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a root-relative link to unbelievable</a> -<a href="http://blog.notmyidea.org/posts/2010/October/15/unbelievable/">a file-relative link to unbelievable</a></p>Alexis MétaireauWed, 20 Apr 2011 00:00:00 +0200tag:blog.notmyidea.org,2011-04-20:posts/2011/April/20/a-markdown-powered-article/Article 1http://blog.notmyidea.org/posts/2011/February/17/article-1/<p>Article 1</p> -Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-1/Article 2http://blog.notmyidea.org/posts/2011/February/17/article-2/<p>Article 2</p> -Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-2/Article 3http://blog.notmyidea.org/posts/2011/February/17/article-3/<p>Article 3</p> -Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/February/17/article-3/ \ No newline at end of file +Alexis' loghttp://blog.notmyidea.org/Wed, 20 Apr 2011 00:00:00 +0200A markdown powered articlehttp://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/<p>You're mutually oblivious.</p> +<p><a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a root-relative link to unbelievable</a> +<a href="http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/">a file-relative link to unbelievable</a></p>Alexis MétaireauWed, 20 Apr 2011 00:00:00 +0200tag:blog.notmyidea.org,2011-04-20:posts/2011/avril/20/a-markdown-powered-article/Article 1http://blog.notmyidea.org/posts/2011/f%C3%A9vrier/17/article-1/<p>Article 1</p> +Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-1/Article 2http://blog.notmyidea.org/posts/2011/f%C3%A9vrier/17/article-2/<p>Article 2</p> +Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-2/Article 3http://blog.notmyidea.org/posts/2011/f%C3%A9vrier/17/article-3/<p>Article 3</p> +Alexis MétaireauThu, 17 Feb 2011 00:00:00 +0100tag:blog.notmyidea.org,2011-02-17:posts/2011/février/17/article-3/ \ No newline at end of file diff --git a/pelican/tests/output/custom_locale/feeds/misc.atom.xml b/pelican/tests/output/custom_locale/feeds/misc.atom.xml index 18800485..c91d4d7e 100644 --- a/pelican/tests/output/custom_locale/feeds/misc.atom.xml +++ b/pelican/tests/output/custom_locale/feeds/misc.atom.xml @@ -1,9 +1,9 @@ -Alexis' loghttp://blog.notmyidea.org/2012-11-30T00:00:00+01:00FILENAME_METADATA example2012-11-30T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-11-30:posts/2012/November/30/filename_metadata-example/<p>Some cool stuff!</p> -Second article2012-02-29T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-02-29:posts/2012/February/29/second-article/<p>This is some article, in english</p> -Unbelievable !2010-10-15T20:30:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-15:posts/2010/October/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> -<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> -<a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> +Alexis' loghttp://blog.notmyidea.org/2012-11-30T00:00:00+01:00FILENAME_METADATA example2012-11-30T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-11-30:posts/2012/novembre/30/filename_metadata-example/<p>Some cool stuff!</p> +Second article2012-02-29T00:00:00+01:00Alexis Métaireautag:blog.notmyidea.org,2012-02-29:posts/2012/février/29/second-article/<p>This is some article, in english</p> +Unbelievable !2010-10-15T20:30:00+02:00Alexis Métaireautag:blog.notmyidea.org,2010-10-15:posts/2010/octobre/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> +<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> +<a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> <div class="section" id="testing-sourcecode-directive"> <h2>Testing sourcecode directive</h2> <table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span class="n">formatter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="ow">and</span> <span class="n">VARIANTS</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]]</span> diff --git a/pelican/tests/output/custom_locale/feeds/misc.rss.xml b/pelican/tests/output/custom_locale/feeds/misc.rss.xml index 0be49f79..82b58983 100644 --- a/pelican/tests/output/custom_locale/feeds/misc.rss.xml +++ b/pelican/tests/output/custom_locale/feeds/misc.rss.xml @@ -1,9 +1,9 @@ -Alexis' loghttp://blog.notmyidea.org/Fri, 30 Nov 2012 00:00:00 +0100FILENAME_METADATA examplehttp://blog.notmyidea.org/posts/2012/November/30/filename_metadata-example/<p>Some cool stuff!</p> -Alexis MétaireauFri, 30 Nov 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-11-30:posts/2012/November/30/filename_metadata-example/Second articlehttp://blog.notmyidea.org/posts/2012/February/29/second-article/<p>This is some article, in english</p> -Alexis MétaireauWed, 29 Feb 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-02-29:posts/2012/February/29/second-article/foobarbazUnbelievable !http://blog.notmyidea.org/posts/2010/October/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> -<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> -<a class="reference external" href="http://blog.notmyidea.org/posts/2011/April/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> +Alexis' loghttp://blog.notmyidea.org/Fri, 30 Nov 2012 00:00:00 +0100FILENAME_METADATA examplehttp://blog.notmyidea.org/posts/2012/novembre/30/filename_metadata-example/<p>Some cool stuff!</p> +Alexis MétaireauFri, 30 Nov 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-11-30:posts/2012/novembre/30/filename_metadata-example/Second articlehttp://blog.notmyidea.org/posts/2012/f%C3%A9vrier/29/second-article/<p>This is some article, in english</p> +Alexis MétaireauWed, 29 Feb 2012 00:00:00 +0100tag:blog.notmyidea.org,2012-02-29:posts/2012/février/29/second-article/foobarbazUnbelievable !http://blog.notmyidea.org/posts/2010/octobre/15/unbelievable/<p>Or completely awesome. Depends the needs.</p> +<p><a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a root-relative link to markdown-article</a> +<a class="reference external" href="http://blog.notmyidea.org/posts/2011/avril/20/a-markdown-powered-article/">a file-relative link to markdown-article</a></p> <div class="section" id="testing-sourcecode-directive"> <h2>Testing sourcecode directive</h2> <table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="highlight"><pre><span class="n">formatter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="ow">and</span> <span class="n">VARIANTS</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]]</span> @@ -34,5 +34,5 @@ pelican.conf, it will have nothing in default.</p> </pre></div> <p>Lovely.</p> </div> -Alexis MétaireauFri, 15 Oct 2010 20:30:00 +0200tag:blog.notmyidea.org,2010-10-15:posts/2010/October/15/unbelievable/The baz taghttp://blog.notmyidea.org/tag/baz.html<p>This article overrides the listening of the articles under the <em>baz</em> tag.</p> +Alexis MétaireauFri, 15 Oct 2010 20:30:00 +0200tag:blog.notmyidea.org,2010-10-15:posts/2010/octobre/15/unbelievable/The baz taghttp://blog.notmyidea.org/tag/baz.html<p>This article overrides the listening of the articles under the <em>baz</em> tag.</p> Alexis MétaireauSun, 14 Mar 2010 00:00:00 +0100tag:blog.notmyidea.org,2010-03-14:tag/baz.html \ No newline at end of file diff --git a/pelican/tests/output/custom_locale/feeds/yeah.atom.xml b/pelican/tests/output/custom_locale/feeds/yeah.atom.xml index 5f7d8c4f..a8dbb270 100644 --- a/pelican/tests/output/custom_locale/feeds/yeah.atom.xml +++ b/pelican/tests/output/custom_locale/feeds/yeah.atom.xml @@ -1,5 +1,5 @@ -Alexis' loghttp://blog.notmyidea.org/2013-11-17T23:29:00+01:00This is a super article !2013-11-17T23:29:00+01:00Alexis Métaireautag:blog.notmyidea.org,2010-12-02:posts/2010/December/02/this-is-a-super-article/<p>Some content here !</p> +Alexis' loghttp://blog.notmyidea.org/2013-11-17T23:29:00+01:00This is a super article !2013-11-17T23:29:00+01:00Alexis Métaireautag:blog.notmyidea.org,2010-12-02:posts/2010/décembre/02/this-is-a-super-article/<p>Some content here !</p> <div class="section" id="this-is-a-simple-title"> <h2>This is a simple title</h2> <p>And here comes the cool <a class="reference external" href="http://books.couchdb.org/relax/design-documents/views">stuff</a>.</p> diff --git a/pelican/tests/output/custom_locale/feeds/yeah.rss.xml b/pelican/tests/output/custom_locale/feeds/yeah.rss.xml index 50c5803c..379d1b93 100644 --- a/pelican/tests/output/custom_locale/feeds/yeah.rss.xml +++ b/pelican/tests/output/custom_locale/feeds/yeah.rss.xml @@ -1,5 +1,5 @@ -Alexis' loghttp://blog.notmyidea.org/Sun, 17 Nov 2013 23:29:00 +0100This is a super article !http://blog.notmyidea.org/posts/2010/December/02/this-is-a-super-article/<p>Some content here !</p> +Alexis' loghttp://blog.notmyidea.org/Sun, 17 Nov 2013 23:29:00 +0100This is a super article !http://blog.notmyidea.org/posts/2010/d%C3%A9cembre/02/this-is-a-super-article/<p>Some content here !</p> <div class="section" id="this-is-a-simple-title"> <h2>This is a simple title</h2> <p>And here comes the cool <a class="reference external" href="http://books.couchdb.org/relax/design-documents/views">stuff</a>.</p> @@ -11,4 +11,4 @@ </pre> <p>→ And now try with some utf8 hell: ééé</p> </div> -Alexis MétaireauSun, 17 Nov 2013 23:29:00 +0100tag:blog.notmyidea.org,2010-12-02:posts/2010/December/02/this-is-a-super-article/foobarfoobar \ No newline at end of file +Alexis MétaireauSun, 17 Nov 2013 23:29:00 +0100tag:blog.notmyidea.org,2010-12-02:posts/2010/décembre/02/this-is-a-super-article/foobarfoobar \ No newline at end of file diff --git a/pelican/tests/support.py b/pelican/tests/support.py index a4fd2c35..151fa3b6 100644 --- a/pelican/tests/support.py +++ b/pelican/tests/support.py @@ -74,7 +74,7 @@ def mute(returns_output=False): If "returns_output" is True, the function will return a generator yielding the printed lines instead of the return values. - The decorator litterally hijack sys.stdout during each function + The decorator literally hijack sys.stdout during each function execution, so be careful with what you apply it to. >>> def numbers(): diff --git a/pelican/tests/test_contents.py b/pelican/tests/test_contents.py index e64b3804..de297985 100644 --- a/pelican/tests/test_contents.py +++ b/pelican/tests/test_contents.py @@ -4,12 +4,13 @@ from __future__ import unicode_literals, absolute_import import six from sys import platform import locale +import os.path from pelican.tests.support import unittest, get_settings -from pelican.contents import Page, Article, URLWrapper +from pelican.contents import Page, Article, Static, URLWrapper from pelican.settings import DEFAULT_CONFIG -from pelican.utils import truncate_html_words, SafeDatetime +from pelican.utils import path_to_url, truncate_html_words, SafeDatetime from pelican.signals import content_object_init from jinja2.utils import generate_lorem_ipsum @@ -211,17 +212,20 @@ class TestPage(unittest.TestCase): 'link') page = Page(**args) content = page.get_content('http://notmyidea.org') - self.assertEqual(content, ('A simple test, with a ' - 'link')) + self.assertEqual( + content, + ('A simple test, with a ' + 'link')) # Category args['content'] = ('A simple test, with a ' 'link') page = Page(**args) content = page.get_content('http://notmyidea.org') - self.assertEqual(content, - ('A simple test, with a ' - 'link')) + self.assertEqual( + content, + ('A simple test, with a ' + 'link')) def test_intrasite_link(self): # type does not take unicode in PY2 and bytes in PY3, which in @@ -401,6 +405,173 @@ class TestArticle(TestPage): self.assertEqual(article.save_as, 'obrien/csharp-stuff/fnord/index.html') +class TestStatic(unittest.TestCase): + + def setUp(self): + + self.settings = get_settings( + STATIC_SAVE_AS='{path}', + STATIC_URL='{path}', + PAGE_SAVE_AS=os.path.join('outpages', '{slug}.html'), + PAGE_URL='outpages/{slug}.html') + self.context = self.settings.copy() + + self.static = Static(content=None, metadata={}, settings=self.settings, + source_path=os.path.join('dir', 'foo.jpg'), context=self.context) + + self.context['filenames'] = {self.static.source_path: self.static} + + def tearDown(self): + pass + + def test_attach_to_same_dir(self): + """attach_to() overrides a static file's save_as and url. + """ + page = Page(content="fake page", + metadata={'title': 'fakepage'}, settings=self.settings, + source_path=os.path.join('dir', 'fakepage.md')) + self.static.attach_to(page) + + expected_save_as = os.path.join('outpages', 'foo.jpg') + self.assertEqual(self.static.save_as, expected_save_as) + self.assertEqual(self.static.url, path_to_url(expected_save_as)) + + def test_attach_to_parent_dir(self): + """attach_to() preserves dirs inside the linking document dir. + """ + page = Page(content="fake page", metadata={'title': 'fakepage'}, + settings=self.settings, source_path='fakepage.md') + self.static.attach_to(page) + + expected_save_as = os.path.join('outpages', 'dir', 'foo.jpg') + self.assertEqual(self.static.save_as, expected_save_as) + self.assertEqual(self.static.url, path_to_url(expected_save_as)) + + def test_attach_to_other_dir(self): + """attach_to() ignores dirs outside the linking document dir. + """ + page = Page(content="fake page", + metadata={'title': 'fakepage'}, settings=self.settings, + source_path=os.path.join('dir', 'otherdir', 'fakepage.md')) + self.static.attach_to(page) + + expected_save_as = os.path.join('outpages', 'foo.jpg') + self.assertEqual(self.static.save_as, expected_save_as) + self.assertEqual(self.static.url, path_to_url(expected_save_as)) + + def test_attach_to_ignores_subsequent_calls(self): + """attach_to() does nothing when called a second time. + """ + page = Page(content="fake page", + metadata={'title': 'fakepage'}, settings=self.settings, + source_path=os.path.join('dir', 'fakepage.md')) + + self.static.attach_to(page) + + otherdir_settings = self.settings.copy() + otherdir_settings.update(dict( + PAGE_SAVE_AS=os.path.join('otherpages', '{slug}.html'), + PAGE_URL='otherpages/{slug}.html')) + otherdir_page = Page(content="other page", + metadata={'title': 'otherpage'}, settings=otherdir_settings, + source_path=os.path.join('dir', 'otherpage.md')) + + self.static.attach_to(otherdir_page) + + otherdir_save_as = os.path.join('otherpages', 'foo.jpg') + self.assertNotEqual(self.static.save_as, otherdir_save_as) + self.assertNotEqual(self.static.url, path_to_url(otherdir_save_as)) + + def test_attach_to_does_nothing_after_save_as_referenced(self): + """attach_to() does nothing if the save_as was already referenced. + (For example, by a {filename} link an a document processed earlier.) + """ + original_save_as = self.static.save_as + + page = Page(content="fake page", + metadata={'title': 'fakepage'}, settings=self.settings, + source_path=os.path.join('dir', 'fakepage.md')) + self.static.attach_to(page) + + self.assertEqual(self.static.save_as, original_save_as) + self.assertEqual(self.static.url, path_to_url(original_save_as)) + + def test_attach_to_does_nothing_after_url_referenced(self): + """attach_to() does nothing if the url was already referenced. + (For example, by a {filename} link an a document processed earlier.) + """ + original_url = self.static.url + + page = Page(content="fake page", + metadata={'title': 'fakepage'}, settings=self.settings, + source_path=os.path.join('dir', 'fakepage.md')) + self.static.attach_to(page) + + self.assertEqual(self.static.save_as, self.static.source_path) + self.assertEqual(self.static.url, original_url) + + def test_attach_to_does_not_override_an_override(self): + """attach_to() does not override paths that were overridden elsewhere. + (For example, by the user with EXTRA_PATH_METADATA) + """ + customstatic = Static(content=None, + metadata=dict(save_as='customfoo.jpg', url='customfoo.jpg'), + settings=self.settings, + source_path=os.path.join('dir', 'foo.jpg'), + context=self.settings.copy()) + + page = Page(content="fake page", + metadata={'title': 'fakepage'}, settings=self.settings, + source_path=os.path.join('dir', 'fakepage.md')) + + customstatic.attach_to(page) + + self.assertEqual(customstatic.save_as, 'customfoo.jpg') + self.assertEqual(customstatic.url, 'customfoo.jpg') + + def test_attach_link_syntax(self): + """{attach} link syntax triggers output path override & url replacement. + """ + html = 'link' + page = Page(content=html, + metadata={'title': 'fakepage'}, settings=self.settings, + source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), + context=self.context) + content = page.get_content('') + + self.assertNotEqual(content, html, + "{attach} link syntax did not trigger URL replacement.") + + expected_save_as = os.path.join('outpages', 'foo.jpg') + self.assertEqual(self.static.save_as, expected_save_as) + self.assertEqual(self.static.url, path_to_url(expected_save_as)) + + def test_tag_link_syntax(self): + "{tag} link syntax triggers url replacement." + + html = 'link' + page = Page( + content=html, + metadata={'title': 'fakepage'}, settings=self.settings, + source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), + context=self.context) + content = page.get_content('') + + self.assertNotEqual(content, html) + + def test_category_link_syntax(self): + "{category} link syntax triggers url replacement." + + html = 'link' + page = Page(content=html, + metadata={'title': 'fakepage'}, settings=self.settings, + source_path=os.path.join('dir', 'otherdir', 'fakepage.md'), + context=self.context) + content = page.get_content('') + + self.assertNotEqual(content, html) + + class TestURLWrapper(unittest.TestCase): def test_comparisons(self): # URLWrappers are sorted by name diff --git a/pelican/tests/test_generators.py b/pelican/tests/test_generators.py index 470d3236..c3e36bc1 100644 --- a/pelican/tests/test_generators.py +++ b/pelican/tests/test_generators.py @@ -12,7 +12,7 @@ from shutil import rmtree from tempfile import mkdtemp from pelican.generators import (Generator, ArticlesGenerator, PagesGenerator, - TemplatePagesGenerator) + StaticGenerator, TemplatePagesGenerator) from pelican.writers import Writer from pelican.tests.support import unittest, get_settings import locale @@ -41,6 +41,38 @@ class TestGenerator(unittest.TestCase): self.assertTrue(include_path(filename, extensions=('rst',))) self.assertFalse(include_path(filename, extensions=('md',))) + def test_get_files_exclude(self): + """Test that Generator.get_files() properly excludes directories. + """ + # We use our own Generator so we can give it our own content path + generator = Generator(context=self.settings.copy(), + settings=self.settings, + path=os.path.join(CUR_DIR, 'nested_content'), + theme=self.settings['THEME'], output_path=None) + + filepaths = generator.get_files(paths=['maindir']) + found_files = {os.path.basename(f) for f in filepaths} + expected_files = {'maindir.md', 'subdir.md'} + self.assertFalse(expected_files - found_files, + "get_files() failed to find one or more files") + + filepaths = generator.get_files(paths=[''], exclude=['maindir']) + found_files = {os.path.basename(f) for f in filepaths} + self.assertNotIn('maindir.md', found_files, + "get_files() failed to exclude a top-level directory") + self.assertNotIn('subdir.md', found_files, + "get_files() failed to exclude a subdir of an excluded directory") + + filepaths = generator.get_files(paths=[''], + exclude=[os.path.join('maindir', 'subdir')]) + found_files = {os.path.basename(f) for f in filepaths} + self.assertNotIn('subdir.md', found_files, + "get_files() failed to exclude a subdirectory") + + filepaths = generator.get_files(paths=[''], exclude=['subdir']) + found_files = {os.path.basename(f) for f in filepaths} + self.assertIn('subdir.md', found_files, + "get_files() excluded a subdirectory by name, ignoring its path") class TestArticlesGenerator(unittest.TestCase): @@ -396,6 +428,7 @@ class TestPageGenerator(unittest.TestCase): ['This is a markdown test page', 'published', 'page'], ['This is a test page with a preset template', 'published', 'custom'], + ['Page with a bunch of links', 'published', 'page'], ['A Page (Test) for sorting', 'published', 'page'], ] hidden_pages_expected = [ @@ -485,6 +518,7 @@ class TestPageGenerator(unittest.TestCase): ['This is a test page', 'published', 'page'], ['This is a markdown test page', 'published', 'page'], ['A Page (Test) for sorting', 'published', 'page'], + ['Page with a bunch of links', 'published', 'page'], ['This is a test page with a preset template', 'published', 'custom'], ] @@ -498,6 +532,7 @@ class TestPageGenerator(unittest.TestCase): # sort by title pages_expected_sorted_by_title = [ ['A Page (Test) for sorting', 'published', 'page'], + ['Page with a bunch of links', 'published', 'page'], ['This is a markdown test page', 'published', 'page'], ['This is a test page', 'published', 'page'], ['This is a test page with a preset template', 'published', @@ -511,6 +546,26 @@ class TestPageGenerator(unittest.TestCase): pages = self.distill_pages(generator.pages) self.assertEqual(pages_expected_sorted_by_title, pages) + def test_tag_and_category_links_on_generated_pages(self): + """ + Test to ensure links of the form {tag}tagname and {category}catname + are generated correctly on pages + """ + settings = get_settings(filenames={}) + settings['PAGE_PATHS'] = ['TestPages'] # relative to CUR_DIR + settings['CACHE_PATH'] = self.temp_cache + settings['DEFAULT_DATE'] = (1970, 1, 1) + + generator = PagesGenerator( + context=settings.copy(), settings=settings, + path=CUR_DIR, theme=settings['THEME'], output_path=None) + generator.generate_context() + pages_by_title = {p.title: p.content for p in generator.pages} + + test_content = pages_by_title['Page with a bunch of links'] + self.assertIn('', test_content) + self.assertIn('', test_content) + class TestTemplatePagesGenerator(unittest.TestCase): @@ -558,3 +613,69 @@ class TestTemplatePagesGenerator(unittest.TestCase): # output content is correct with open(output_path, 'r') as output_file: self.assertEqual(output_file.read(), 'foo: bar') + + +class TestStaticGenerator(unittest.TestCase): + + def setUp(self): + self.content_path = os.path.join(CUR_DIR, 'mixed_content') + + def test_static_excludes(self): + """Test that StaticGenerator respects STATIC_EXCLUDES. + """ + settings = get_settings(STATIC_EXCLUDES=['subdir'], + PATH=self.content_path, STATIC_PATHS=['']) + context = settings.copy() + context['filenames'] = {} + + StaticGenerator(context=context, settings=settings, + path=settings['PATH'], output_path=None, + theme=settings['THEME']).generate_context() + + staticnames = [os.path.basename(c.source_path) + for c in context['staticfiles']] + + self.assertNotIn('subdir_fake_image.jpg', staticnames, + "StaticGenerator processed a file in a STATIC_EXCLUDES directory") + self.assertIn('fake_image.jpg', staticnames, + "StaticGenerator skipped a file that it should have included") + + def test_static_exclude_sources(self): + """Test that StaticGenerator respects STATIC_EXCLUDE_SOURCES. + """ + # Test STATIC_EXCLUDE_SOURCES=True + + settings = get_settings(STATIC_EXCLUDE_SOURCES=True, + PATH=self.content_path, PAGE_PATHS=[''], STATIC_PATHS=[''], + CACHE_CONTENT=False) + context = settings.copy() + context['filenames'] = {} + + for generator_class in (PagesGenerator, StaticGenerator): + generator_class(context=context, settings=settings, + path=settings['PATH'], output_path=None, + theme=settings['THEME']).generate_context() + + staticnames = [os.path.basename(c.source_path) + for c in context['staticfiles']] + + self.assertFalse(any(name.endswith(".md") for name in staticnames), + "STATIC_EXCLUDE_SOURCES=True failed to exclude a markdown file") + + # Test STATIC_EXCLUDE_SOURCES=False + + settings.update(STATIC_EXCLUDE_SOURCES=False) + context = settings.copy() + context['filenames'] = {} + + for generator_class in (PagesGenerator, StaticGenerator): + generator_class(context=context, settings=settings, + path=settings['PATH'], output_path=None, + theme=settings['THEME']).generate_context() + + staticnames = [os.path.basename(c.source_path) + for c in context['staticfiles']] + + self.assertTrue(any(name.endswith(".md") for name in staticnames), + "STATIC_EXCLUDE_SOURCES=False failed to include a markdown file") + diff --git a/pelican/tests/test_pelican.py b/pelican/tests/test_pelican.py index c851ef81..190d5e06 100644 --- a/pelican/tests/test_pelican.py +++ b/pelican/tests/test_pelican.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals, print_function +import collections import os import sys from tempfile import mkdtemp @@ -10,6 +11,7 @@ import logging import subprocess from pelican import Pelican +from pelican.generators import StaticGenerator from pelican.settings import read_settings from pelican.tests.support import LoggedTestCase, mute, locale_available, unittest @@ -75,6 +77,19 @@ class TestPelican(LoggedTestCase): assert not out, out assert not err, err + def test_order_of_generators(self): + # StaticGenerator must run last, so it can identify files that + # were skipped by the other generators, and so static files can + # have their output paths overridden by the {attach} link syntax. + + pelican = Pelican(settings=read_settings(path=None)) + generator_classes = pelican.get_generator_classes() + + self.assertTrue(generator_classes[-1] is StaticGenerator, + "StaticGenerator must be the last generator, but it isn't!") + self.assertIsInstance(generator_classes, collections.Sequence, + "get_generator_classes() must return a Sequence to preserve order") + def test_basic_generation_works(self): # when running pelican without settings, it should pick up the default # ones and generate correct output without raising any exception diff --git a/pelican/tests/test_rstdirectives.py b/pelican/tests/test_rstdirectives.py new file mode 100644 index 00000000..ae863b30 --- /dev/null +++ b/pelican/tests/test_rstdirectives.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals, print_function + +from mock import Mock +from pelican.tests.support import unittest + +class Test_abbr_role(unittest.TestCase): + def call_it(self, text): + from pelican.rstdirectives import abbr_role + rawtext = text + lineno = 42 + inliner = Mock(name='inliner') + nodes, system_messages = abbr_role( + 'abbr', rawtext, text, lineno, inliner) + self.assertEqual(system_messages, []) + self.assertEqual(len(nodes), 1) + return nodes[0] + + def test(self): + node = self.call_it("Abbr (Abbreviation)") + self.assertEqual(node.astext(), "Abbr") + self.assertEqual(node['explanation'], "Abbreviation") + + def test_newlines_in_explanation(self): + node = self.call_it("CUL (See you\nlater)") + self.assertEqual(node.astext(), "CUL") + self.assertEqual(node['explanation'], "See you\nlater") + + def test_newlines_in_abbr(self): + node = self.call_it("US of\nA \n (USA)") + self.assertEqual(node.astext(), "US of\nA") + self.assertEqual(node['explanation'], "USA") diff --git a/pelican/tests/test_utils.py b/pelican/tests/test_utils.py index 18740f21..7c9e6e5a 100644 --- a/pelican/tests/test_utils.py +++ b/pelican/tests/test_utils.py @@ -471,7 +471,7 @@ class TestDateFormatter(unittest.TestCase): locale_available('French'), 'French locale needed') def test_french_strftime(self): - # This test tries to reproduce an issue that occured with python3.3 under macos10 only + # This test tries to reproduce an issue that occurred with python3.3 under macos10 only locale.setlocale(locale.LC_ALL, str('fr_FR.UTF-8')) date = utils.SafeDatetime(2014,8,14) # we compare the lower() dates since macos10 returns "Jeudi" for %A whereas linux reports "jeudi" diff --git a/pelican/themes/notmyidea/templates/analytics.html b/pelican/themes/notmyidea/templates/analytics.html index c3499c81..e27adf82 100644 --- a/pelican/themes/notmyidea/templates/analytics.html +++ b/pelican/themes/notmyidea/templates/analytics.html @@ -25,3 +25,22 @@ })(); {% endif %} +{% if PIWIK_URL and PIWIK_SITE_ID %} + +{% endif %} diff --git a/pelican/themes/notmyidea/templates/base.html b/pelican/themes/notmyidea/templates/base.html index b081515f..d6b4cb35 100644 --- a/pelican/themes/notmyidea/templates/base.html +++ b/pelican/themes/notmyidea/templates/base.html @@ -77,7 +77,6 @@ {% include 'analytics.html' %} -{% include 'piwik.html' %} {% include 'disqus_script.html' %} diff --git a/pelican/themes/notmyidea/templates/piwik.html b/pelican/themes/notmyidea/templates/piwik.html deleted file mode 100644 index f9126264..00000000 --- a/pelican/themes/notmyidea/templates/piwik.html +++ /dev/null @@ -1,19 +0,0 @@ -{% if PIWIK_URL and PIWIK_SITE_ID %} - -{% endif %} diff --git a/pelican/themes/simple/templates/authors.html b/pelican/themes/simple/templates/authors.html index fa9b5170..4914904f 100644 --- a/pelican/themes/simple/templates/authors.html +++ b/pelican/themes/simple/templates/authors.html @@ -4,7 +4,10 @@ {% block content %}

Authors on {{ SITENAME }}

+ +
{% endblock %} diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index b24a508c..74633630 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -9,6 +9,7 @@ import string import argparse import sys import codecs +import pytz from pelican import __version__ @@ -39,9 +40,13 @@ CONF = { 'github_pages_branch': _GITHUB_PAGES_BRANCHES['project'], 'default_pagination': 10, 'siteurl': '', - 'lang': 'en' + 'lang': 'en', + 'timezone': 'Europe/Paris' } +#url for list of valid timezones +_TZ_URL = 'http://en.wikipedia.org/wiki/List_of_tz_database_time_zones' + def _input_compat(prompt): if six.PY3: r = input(prompt) @@ -155,6 +160,20 @@ def ask(question, answer=str_compat, default=None, l=None): raise NotImplemented('Argument `answer` must be str_compat, bool, or integer') +def ask_timezone(question, default, tzurl): + """Prompt for time zone and validate input""" + lower_tz = map(str.lower, pytz.all_timezones) + while True: + r = ask(question, str_compat, default) + r = r.strip().replace(' ', '_').lower() + if r in lower_tz: + r = pytz.all_timezones[lower_tz.index(r)] + break + else: + print('Please enter a valid time zone:\n (check [{0}])'.format(tzurl)) + return r + + def main(): parser = argparse.ArgumentParser( description="A kickstarter for Pelican", @@ -203,6 +222,8 @@ needed by Pelican. else: CONF['default_pagination'] = False + CONF['timezone'] = ask_timezone('What is your time zone?', CONF['timezone'], _TZ_URL) + automation = ask('Do you want to generate a Fabfile/Makefile to automate generation and publishing?', bool, True) develop = ask('Do you want an auto-reload & simpleHTTP script to assist with theme and site development?', bool, True) diff --git a/pelican/tools/templates/Makefile.in b/pelican/tools/templates/Makefile.in index a8ffd6ca..8534595e 100644 --- a/pelican/tools/templates/Makefile.in +++ b/pelican/tools/templates/Makefile.in @@ -97,7 +97,7 @@ ftp_upload: publish lftp ftp://$$(FTP_USER)@$$(FTP_HOST) -e "mirror -R $$(OUTPUTDIR) $$(FTP_TARGET_DIR) ; quit" s3_upload: publish - s3cmd sync $(OUTPUTDIR)/ s3://$(S3_BUCKET) --acl-public --delete-removed --guess-mime-type + s3cmd sync $(OUTPUTDIR)/ s3://$(S3_BUCKET) --acl-public --delete-removed --guess-mime-type cf_upload: publish cd $(OUTPUTDIR) && swift -v -A https://auth.api.rackspacecloud.com/v1.0 -U $(CLOUDFILES_USERNAME) -K $(CLOUDFILES_API_KEY) upload -c $(CLOUDFILES_CONTAINER) . diff --git a/pelican/tools/templates/fabfile.py.in b/pelican/tools/templates/fabfile.py.in index e693bb48..a8ab586b 100644 --- a/pelican/tools/templates/fabfile.py.in +++ b/pelican/tools/templates/fabfile.py.in @@ -1,6 +1,7 @@ from fabric.api import * import fabric.contrib.project as project import os +import shutil import sys import SimpleHTTPServer import SocketServer @@ -18,26 +19,35 @@ env.cloudfiles_username = '$cloudfiles_username' env.cloudfiles_api_key = '$cloudfiles_api_key' env.cloudfiles_container = '$cloudfiles_container' +# Github Pages configuration +env.github_pages_branch = "gh-pages" + +# Port for `serve` +PORT = 8000 def clean(): + """Remove generated files""" if os.path.isdir(DEPLOY_PATH): - local('rm -rf {deploy_path}'.format(**env)) - local('mkdir {deploy_path}'.format(**env)) + shutil.rmtree(DEPLOY_PATH) + os.makedirs(DEPLOY_PATH) def build(): + """Build local version of site""" local('pelican -s pelicanconf.py') def rebuild(): + """`clean` then `build`""" clean() build() def regenerate(): + """Automatically regenerate site upon file modification""" local('pelican -r -s pelicanconf.py') def serve(): + """Serve site at http://localhost:8000/""" os.chdir(env.deploy_path) - PORT = 8000 class AddressReuseTCPServer(SocketServer.TCPServer): allow_reuse_address = True @@ -47,22 +57,26 @@ def serve(): server.serve_forever() def reserve(): + """`build`, then `serve`""" build() serve() def preview(): + """Build production version of site""" local('pelican -s publishconf.py') def cf_upload(): + """Publish to Rackspace Cloud Files""" rebuild() - local('cd {deploy_path} && ' - 'swift -v -A https://auth.api.rackspacecloud.com/v1.0 ' - '-U {cloudfiles_username} ' - '-K {cloudfiles_api_key} ' - 'upload -c {cloudfiles_container} .'.format(**env)) + with lcd(DEPLOY_PATH): + local('swift -v -A https://auth.api.rackspacecloud.com/v1.0 ' + '-U {cloudfiles_username} ' + '-K {cloudfiles_api_key} ' + 'upload -c {cloudfiles_container} .'.format(**env)) @hosts(production) def publish(): + """Publish to production via rsync""" local('pelican -s publishconf.py') project.rsync_project( remote_dir=dest_path, @@ -71,3 +85,9 @@ def publish(): delete=True, extra_opts='-c', ) + +def gh_pages(): + """Publish to GitHub Pages""" + rebuild() + local("ghp-import -b {github_pages_branch} {deploy_path}".format(**env)) + local("git push origin {github_pages_branch}".format(**env)) diff --git a/pelican/tools/templates/pelicanconf.py.in b/pelican/tools/templates/pelicanconf.py.in index 1a02a9de..05d1a323 100644 --- a/pelican/tools/templates/pelicanconf.py.in +++ b/pelican/tools/templates/pelicanconf.py.in @@ -8,7 +8,7 @@ SITEURL = '' PATH = 'content' -TIMEZONE = 'Europe/Paris' +TIMEZONE = $timezone DEFAULT_LANG = $lang @@ -16,6 +16,8 @@ DEFAULT_LANG = $lang FEED_ALL_ATOM = None CATEGORY_FEED_ATOM = None TRANSLATION_FEED_ATOM = None +AUTHOR_FEED_ATOM = None +AUTHOR_FEED_RSS = None # Blogroll LINKS = (('Pelican', 'http://getpelican.com/'), diff --git a/pelican/urlwrappers.py b/pelican/urlwrappers.py index f92d1963..06cfa2ab 100644 --- a/pelican/urlwrappers.py +++ b/pelican/urlwrappers.py @@ -70,7 +70,7 @@ class URLWrapper(object): setting = "%s_%s" % (self.__class__.__name__.upper(), key) value = self.settings[setting] if not isinstance(value, six.string_types): - logger.warning('%s is set to %s', (setting, value)) + logger.warning('%s is set to %s', setting, value) return value else: if get_page_name: diff --git a/pelican/utils.py b/pelican/utils.py index 1f8cb0a6..f216b027 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -681,7 +681,7 @@ class FileStampDataCacher(FileDataCacher): '''Subclass that also caches the stamp of the file''' def __init__(self, settings, cache_name, caching_policy, load_policy): - '''This sublcass additionaly sets filestamp function + '''This sublcass additionally sets filestamp function and base path for filestamping operations ''' super(FileStampDataCacher, self).__init__(settings, cache_name, diff --git a/pelican/writers.py b/pelican/writers.py index 43d64b34..bf32e272 100644 --- a/pelican/writers.py +++ b/pelican/writers.py @@ -93,39 +93,36 @@ class Writer(object): """ if not is_selected_for_writing(self.settings, path): return - old_locale = locale.setlocale(locale.LC_ALL) - locale.setlocale(locale.LC_ALL, str('C')) - try: - self.site_url = context.get( - 'SITEURL', path_to_url(get_relative_path(path))) - self.feed_domain = context.get('FEED_DOMAIN') - self.feed_url = '{}/{}'.format(self.feed_domain, path) + self.site_url = context.get( + 'SITEURL', path_to_url(get_relative_path(path))) - feed = self._create_new_feed(feed_type, context) + self.feed_domain = context.get('FEED_DOMAIN') + self.feed_url = '{}/{}'.format(self.feed_domain, path) - max_items = len(elements) - if self.settings['FEED_MAX_ITEMS']: - max_items = min(self.settings['FEED_MAX_ITEMS'], max_items) - for i in range(max_items): - self._add_item_to_the_feed(feed, elements[i]) + feed = self._create_new_feed(feed_type, context) - if path: - complete_path = os.path.join(self.output_path, path) - try: - os.makedirs(os.path.dirname(complete_path)) - except Exception: - pass + max_items = len(elements) + if self.settings['FEED_MAX_ITEMS']: + max_items = min(self.settings['FEED_MAX_ITEMS'], max_items) + for i in range(max_items): + self._add_item_to_the_feed(feed, elements[i]) - encoding = 'utf-8' if six.PY3 else None - with self._open_w(complete_path, encoding) as fp: - feed.write(fp, 'utf-8') - logger.info('Writing %s', complete_path) + if path: + complete_path = os.path.join(self.output_path, path) + try: + os.makedirs(os.path.dirname(complete_path)) + except Exception: + pass + + encoding = 'utf-8' if six.PY3 else None + with self._open_w(complete_path, encoding) as fp: + feed.write(fp, 'utf-8') + logger.info('Writing %s', complete_path) + + signals.feed_written.send(complete_path, context=context, feed=feed) + return feed - signals.feed_written.send(complete_path, context=context, feed=feed) - return feed - finally: - locale.setlocale(locale.LC_ALL, old_locale) def write_file(self, name, template, context, relative_urls=False, paginated=None, override_output=False, **kwargs): diff --git a/setup.py b/setup.py index c1af72bb..8e4eff34 100755 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ CHANGELOG = open('docs/changelog.rst').read() setup( name="pelican", - version="3.4.0", + version="3.5.0", url='http://getpelican.com/', author='Alexis Metaireau', author_email='authors@getpelican.com',