mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Merge pull request #2381 from oulenz/static_links
Automatically copy linked static files
This commit is contained in:
commit
0da7ac677a
32 changed files with 424 additions and 224 deletions
|
|
@ -14,6 +14,9 @@ Next release
|
|||
and author pages 2) feeds 3) draft and hidden articles and pages
|
||||
* New ``ARTICLE_TRANSLATION_ID`` and ``PAGE_TRANSLATION_ID`` settings to specify
|
||||
metadata attributes used to identify translations; or to disable translations
|
||||
* New ``{static}`` syntax to link to static content; content linked to by
|
||||
``{static}`` and ``{attach}`` is automatically copied over even if not in
|
||||
``STATIC_PATHS``
|
||||
|
||||
3.7.1 (2017-01-10)
|
||||
==================
|
||||
|
|
|
|||
|
|
@ -168,6 +168,34 @@ If you want to exclude any pages from being linked to or listed in the menu
|
|||
then add a ``status: hidden`` attribute to its metadata. This is useful for
|
||||
things like making error pages that fit the generated theme of your site.
|
||||
|
||||
Static content
|
||||
==============
|
||||
|
||||
Static files are files other than articles and pages that are copied to the
|
||||
output folder as-is, without processing. You can control which static files
|
||||
are copied over with 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. In addition,
|
||||
static files that are explicitly linked to are included (see below).
|
||||
|
||||
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.
|
||||
|
||||
.. _ref-linking-to-internal-content:
|
||||
|
||||
Linking to internal content
|
||||
|
|
@ -221,13 +249,10 @@ and ``article2.md``::
|
|||
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.
|
||||
You can link to static content using ``{static}path/to/file``. Files linked to
|
||||
with this syntax will automatically be copied to the output directory, even if
|
||||
the source directories containing them are not included in the ``STATIC_PATHS``
|
||||
setting of the project's ``pelicanconf.py`` file.
|
||||
|
||||
For example, a project's content directory might be structured like this::
|
||||
|
||||
|
|
@ -241,48 +266,28 @@ For example, a project's content directory might be structured like this::
|
|||
|
||||
``test.md`` would include::
|
||||
|
||||

|
||||
[Our Menu]({filename}/pdfs/menu.pdf)
|
||||
|
||||
``pelicanconf.py`` would include::
|
||||
|
||||
STATIC_PATHS = ['images', 'pdfs']
|
||||

|
||||
[Our Menu]({static}/pdfs/menu.pdf)
|
||||
|
||||
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``.
|
||||
|
||||
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.
|
||||
If you use ``{static}`` to link to an article or a page, this will be turned into
|
||||
a link to its source code.
|
||||
|
||||
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
|
||||
like the ``{static}`` 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.
|
||||
This only works for linking to static files.
|
||||
|
||||
For example, a project's content directory might be structured like this::
|
||||
|
||||
|
|
@ -298,7 +303,6 @@ For example, a project's content directory might be structured like this::
|
|||
``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'
|
||||
|
|
@ -328,7 +332,7 @@ 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}``.
|
||||
After the first link, Pelican will treat ``{attach}`` like ``{static}``.
|
||||
This avoids breaking the already-processed links.
|
||||
|
||||
**Be careful when linking to a file from multiple documents:**
|
||||
|
|
@ -342,7 +346,7 @@ 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
|
||||
these precautions are not possible, consider using ``{static}`` 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``.)
|
||||
|
|
@ -360,8 +364,11 @@ 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.
|
||||
extensions or reST directives. Similarly, Pelican also still supports linking to
|
||||
static content with ``{filename}``. The syntax was changed to ``{static}`` to allow
|
||||
linking to both generated articles and pages and their static sources.
|
||||
|
||||
Support for the old syntax may eventually be removed.
|
||||
|
||||
|
||||
Importing an existing site
|
||||
|
|
|
|||
|
|
@ -150,8 +150,11 @@ class Pelican(object):
|
|||
start_time = time.time()
|
||||
|
||||
context = self.settings.copy()
|
||||
# Share these among all the generators and content objects:
|
||||
context['filenames'] = {} # maps source path to Content object or None
|
||||
# Share these among all the generators and content objects
|
||||
# They map source paths to Content objects or None
|
||||
context['generated_content'] = {}
|
||||
context['static_links'] = set()
|
||||
context['static_content'] = {}
|
||||
context['localsiteurl'] = self.settings['SITEURL']
|
||||
|
||||
generators = [
|
||||
|
|
|
|||
|
|
@ -142,7 +142,8 @@ class Content(object):
|
|||
if not hasattr(self, 'status'):
|
||||
self.status = getattr(self, 'default_status', None)
|
||||
|
||||
if len(self._context.get('filenames', [])) > 0:
|
||||
if (len(self._context.get('generated_content', [])) > 0 or
|
||||
len(self._context.get('static_content', [])) > 0):
|
||||
self.refresh_metadata_intersite_links()
|
||||
|
||||
signals.content_object_init.send(self)
|
||||
|
|
@ -255,7 +256,7 @@ class Content(object):
|
|||
siteurl += '/'
|
||||
|
||||
# XXX Put this in a different location.
|
||||
if what in {'filename', 'attach'}:
|
||||
if what in {'filename', 'static', 'attach'}:
|
||||
if path.startswith('/'):
|
||||
path = path[1:]
|
||||
else:
|
||||
|
|
@ -264,22 +265,33 @@ class Content(object):
|
|||
os.path.join(self.relative_dir, path)
|
||||
)
|
||||
|
||||
if path not in self._context['filenames']:
|
||||
unquoted_path = path.replace('%20', ' ')
|
||||
key = 'static_content' if what in ('static', 'attach')\
|
||||
else 'generated_content'
|
||||
|
||||
if unquoted_path in self._context['filenames']:
|
||||
path = unquoted_path
|
||||
def _get_linked_content(key, path):
|
||||
try:
|
||||
return self._context[key][path]
|
||||
except KeyError:
|
||||
try:
|
||||
# Markdown escapes spaces, try unescaping
|
||||
return self._context[key][path.replace('%20', ' ')]
|
||||
except KeyError:
|
||||
if what == 'filename' and key == 'generated_content':
|
||||
key = 'static_content'
|
||||
linked_content = _get_linked_content(key, path)
|
||||
if linked_content:
|
||||
logger.warning(
|
||||
'{filename} used for linking to static'
|
||||
'content %s in %s. Use {static} instead',
|
||||
path,
|
||||
self.get_relative_source_path())
|
||||
return linked_content
|
||||
return None
|
||||
|
||||
linked_content = self._context['filenames'].get(path)
|
||||
linked_content = _get_linked_content(key, 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())
|
||||
linked_content.attach_to(self)
|
||||
origin = joiner(siteurl, linked_content.url)
|
||||
origin = origin.replace('\\', '/') # for Windows paths.
|
||||
else:
|
||||
|
|
@ -310,6 +322,17 @@ class Content(object):
|
|||
return ''.join((m.group('markup'), m.group('quote'), origin,
|
||||
m.group('quote')))
|
||||
|
||||
def _get_intrasite_link_regex(self):
|
||||
intrasite_link_regex = self.settings['INTRASITE_LINK_REGEX']
|
||||
regex = r"""
|
||||
(?P<markup><[^\>]+ # match tag with all url-value attributes
|
||||
(?:href|src|poster|data|cite|formaction|action)\s*=\s*)
|
||||
|
||||
(?P<quote>["\']) # require value to be quoted
|
||||
(?P<path>{0}(?P<value>.*?)) # the url value
|
||||
\2""".format(intrasite_link_regex)
|
||||
return re.compile(regex, re.X)
|
||||
|
||||
def _update_content(self, content, siteurl):
|
||||
"""Update the content attribute.
|
||||
|
||||
|
|
@ -323,18 +346,29 @@ class Content(object):
|
|||
if not content:
|
||||
return content
|
||||
|
||||
instrasite_link_regex = self.settings['INTRASITE_LINK_REGEX']
|
||||
regex = r"""
|
||||
(?P<markup><[^\>]+ # match tag with all url-value attributes
|
||||
(?:href|src|poster|data|cite|formaction|action)\s*=\s*)
|
||||
|
||||
(?P<quote>["\']) # require value to be quoted
|
||||
(?P<path>{0}(?P<value>.*?)) # the url value
|
||||
\2""".format(instrasite_link_regex)
|
||||
hrefs = re.compile(regex, re.X)
|
||||
|
||||
hrefs = self._get_intrasite_link_regex()
|
||||
return hrefs.sub(lambda m: self._link_replacer(siteurl, m), content)
|
||||
|
||||
def get_static_links(self):
|
||||
static_links = set()
|
||||
hrefs = self._get_intrasite_link_regex()
|
||||
for m in hrefs.finditer(self._content):
|
||||
what = m.group('what')
|
||||
value = urlparse(m.group('value'))
|
||||
path = value.path
|
||||
if what not in {'static', 'attach'}:
|
||||
continue
|
||||
if path.startswith('/'):
|
||||
path = path[1:]
|
||||
else:
|
||||
# relative to the source path of this content
|
||||
path = self.get_relative_source_path(
|
||||
os.path.join(self.relative_dir, path)
|
||||
)
|
||||
path = path.replace('%20', ' ')
|
||||
static_links.add(path)
|
||||
return static_links
|
||||
|
||||
def get_siteurl(self):
|
||||
return self._context.get('localsiteurl', '')
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class Generator(object):
|
|||
parent_path, subdir = os.path.split(os.path.join(self.path, e))
|
||||
exclusions_by_dirpath.setdefault(parent_path, set()).add(subdir)
|
||||
|
||||
files = []
|
||||
files = set()
|
||||
ignores = self.settings['IGNORE_FILES']
|
||||
for path in paths:
|
||||
# careful: os.path.join() will add a slash when path == ''.
|
||||
|
|
@ -170,33 +170,41 @@ class Generator(object):
|
|||
for f in temp_files:
|
||||
fp = os.path.join(reldir, f)
|
||||
if self._include_path(fp, extensions):
|
||||
files.append(fp)
|
||||
files.add(fp)
|
||||
elif os.path.exists(root) and self._include_path(path, extensions):
|
||||
files.append(path) # can't walk non-directories
|
||||
files.add(path) # can't walk non-directories
|
||||
return files
|
||||
|
||||
def add_source_path(self, content):
|
||||
def add_source_path(self, content, static=False):
|
||||
"""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
|
||||
key = 'static_content' if static else 'generated_content'
|
||||
self.context[key][location] = content
|
||||
|
||||
def _add_failed_source_path(self, path):
|
||||
def _add_failed_source_path(self, path, static=False):
|
||||
"""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'][posixize_path(os.path.normpath(path))] = None
|
||||
key = 'static_content' if static else 'generated_content'
|
||||
self.context[key][posixize_path(os.path.normpath(path))] = None
|
||||
|
||||
def _is_potential_source_path(self, path):
|
||||
def _is_potential_source_path(self, path, static=False):
|
||||
"""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 (posixize_path(os.path.normpath(path))
|
||||
in self.context['filenames'])
|
||||
key = 'static_content' if static else 'generated_content'
|
||||
return (posixize_path(os.path.normpath(path)) in self.context[key])
|
||||
|
||||
def add_static_links(self, content):
|
||||
"""Add file links in content to context to be processed as Static
|
||||
content.
|
||||
"""
|
||||
self.context['static_links'] |= content.get_static_links()
|
||||
|
||||
def _update_context(self, items):
|
||||
"""Update the context with the given items from the currrent
|
||||
|
|
@ -596,6 +604,7 @@ class ArticlesGenerator(CachingGenerator):
|
|||
elif article.status == "draft":
|
||||
all_drafts.append(article)
|
||||
self.add_source_path(article)
|
||||
self.add_static_links(article)
|
||||
|
||||
def _process(arts):
|
||||
origs, translations = process_translations(
|
||||
|
|
@ -702,6 +711,7 @@ class PagesGenerator(CachingGenerator):
|
|||
elif page.status == "draft":
|
||||
draft_pages.append(page)
|
||||
self.add_source_path(page)
|
||||
self.add_static_links(page)
|
||||
|
||||
def _process(pages):
|
||||
origs, translations = process_translations(
|
||||
|
|
@ -753,9 +763,12 @@ 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):
|
||||
linked_files = {os.path.join(self.path, path)
|
||||
for path in self.context['static_links']}
|
||||
found_files = self.get_files(self.settings['STATIC_PATHS'],
|
||||
exclude=self.settings['STATIC_EXCLUDES'],
|
||||
extensions=False)
|
||||
for f in linked_files | found_files:
|
||||
|
||||
# skip content source files unless the user explicitly wants them
|
||||
if self.settings['STATIC_EXCLUDE_SOURCES']:
|
||||
|
|
@ -770,7 +783,7 @@ class StaticGenerator(Generator):
|
|||
context_signal=signals.static_generator_context,
|
||||
context_sender=self)
|
||||
self.staticfiles.append(static)
|
||||
self.add_source_path(static)
|
||||
self.add_source_path(static, static=True)
|
||||
self._update_context(('staticfiles',))
|
||||
signals.static_generator_finalized.send(self)
|
||||
|
||||
|
|
|
|||
7
pelican/tests/TestPages/page_with_static_links.md
Normal file
7
pelican/tests/TestPages/page_with_static_links.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Title: Page with static links
|
||||
|
||||
My links:
|
||||
|
||||
[Link 0]({static}image0.jpg)
|
||||
|
||||
[Link 1]({attach}image1.jpg)
|
||||
|
|
@ -42,8 +42,8 @@
|
|||
<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>
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<pre class="literal-block">
|
||||
>>> from ipdb import set_trace
|
||||
>>> set_trace()
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
|
||||
<a class="readmore" href="/oh-yeah.html">read more</a>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</article>
|
||||
</aside><!-- /#featured -->
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@
|
|||
<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>
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<pre class="literal-block">
|
||||
>>> from ipdb import set_trace
|
||||
>>> set_trace()
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ as well as <strong>inline markup</strong>.</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>
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<pre class="literal-block">
|
||||
&gt;&gt;&gt; from ipdb import set_trace
|
||||
&gt;&gt;&gt; set_trace()
|
||||
|
|
@ -17,12 +17,12 @@ as well as <strong>inline markup</strong>.</p>
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</summary><content type="html"><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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</content><category term="oh"></category><category term="bar"></category><category term="yeah"></category></entry></feed>
|
||||
|
|
@ -5,6 +5,6 @@ as well as <strong>inline markup</strong>.</p>
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Alexis Métaireau</dc:creator><pubDate>Wed, 20 Oct 2010 10:14:00 +0000</pubDate><guid isPermaLink="false">tag:None,2010-10-20:/oh-yeah.html</guid><category>oh</category><category>bar</category><category>yeah</category></item></channel></rss>
|
||||
|
|
@ -19,8 +19,8 @@ as well as <strong>inline markup</strong>.</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>
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<pre class="literal-block">
|
||||
&gt;&gt;&gt; from ipdb import set_trace
|
||||
&gt;&gt;&gt; set_trace()
|
||||
|
|
@ -31,13 +31,13 @@ as well as <strong>inline markup</strong>.</p>
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</summary><content type="html"><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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</content><category term="oh"></category><category term="bar"></category><category term="yeah"></category></entry><entry><title>Unbelievable !</title><link href="/unbelievable.html" rel="alternate"></link><published>2010-10-15T20:30:00+00:00</published><updated>2010-10-15T20:30:00+00:00</updated><author><name></name></author><id>tag:None,2010-10-15:/unbelievable.html</id><summary type="html"><p>Or completely awesome. Depends the needs.</p>
|
||||
<p><a class="reference external" href="/a-markdown-powered-article.html">a root-relative link to markdown-article</a>
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ as well as <strong>inline markup</strong>.</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>
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<pre class="literal-block">
|
||||
&gt;&gt;&gt; from ipdb import set_trace
|
||||
&gt;&gt;&gt; set_trace()
|
||||
|
|
@ -33,13 +33,13 @@ as well as <strong>inline markup</strong>.</p>
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</summary><content type="html"><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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</content><category term="oh"></category><category term="bar"></category><category term="yeah"></category></entry><entry><title>Unbelievable !</title><link href="/unbelievable.html" rel="alternate"></link><published>2010-10-15T20:30:00+00:00</published><updated>2010-10-15T20:30:00+00:00</updated><author><name></name></author><id>tag:None,2010-10-15:/unbelievable.html</id><summary type="html"><p>Or completely awesome. Depends the needs.</p>
|
||||
<p><a class="reference external" href="/a-markdown-powered-article.html">a root-relative link to markdown-article</a>
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</summary><content type="html"><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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</content><category term="oh"></category><category term="bar"></category><category term="yeah"></category></entry></feed>
|
||||
|
|
@ -5,8 +5,8 @@ as well as <strong>inline markup</strong>.</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>
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<pre class="literal-block">
|
||||
&gt;&gt;&gt; from ipdb import set_trace
|
||||
&gt;&gt;&gt; set_trace()
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ as well as <strong>inline markup</strong>.</p>
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
|
||||
<a class="readmore" href="/oh-yeah.html">read more</a>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
|
||||
</div><!-- /.entry-content -->
|
||||
|
|
|
|||
BIN
pelican/tests/output/basic/pictures/Sushi.jpg
Normal file
BIN
pelican/tests/output/basic/pictures/Sushi.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
pelican/tests/output/basic/pictures/Sushi_Macro.jpg
Normal file
BIN
pelican/tests/output/basic/pictures/Sushi_Macro.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
|
|
@ -90,7 +90,7 @@ as well as <strong>inline markup</strong>.</p>
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
|
||||
<a class="readmore" href="/oh-yeah.html">read more</a>
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@
|
|||
<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>
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<pre class="literal-block">
|
||||
>>> from ipdb import set_trace
|
||||
>>> set_trace()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
<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="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
</div>
|
||||
</article>
|
||||
</aside><!-- /#featured -->
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@
|
|||
<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>
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="|filename|/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi.jpg" style="width: 600px; height: 450px;" />
|
||||
<img alt="alternate text" src="/pictures/Sushi_Macro.jpg" style="width: 600px; height: 450px;" />
|
||||
<pre class="literal-block">
|
||||
>>> from ipdb import set_trace
|
||||
>>> set_trace()
|
||||
|
|
|
|||
|
|
@ -175,6 +175,15 @@ def get_settings(**kwargs):
|
|||
return settings
|
||||
|
||||
|
||||
def get_context(settings=None, **kwargs):
|
||||
context = settings.copy() if settings else {}
|
||||
context['generated_content'] = {}
|
||||
context['static_links'] = set()
|
||||
context['static_content'] = {}
|
||||
context.update(kwargs)
|
||||
return context
|
||||
|
||||
|
||||
class LogCountHandler(BufferingHandler):
|
||||
"""Capturing and counting logged messages."""
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from shutil import rmtree
|
|||
from tempfile import mkdtemp
|
||||
|
||||
from pelican.generators import ArticlesGenerator, PagesGenerator
|
||||
from pelican.tests.support import get_settings, unittest
|
||||
from pelican.tests.support import get_context, get_settings, unittest
|
||||
|
||||
try:
|
||||
from unittest.mock import MagicMock
|
||||
|
|
@ -29,7 +29,7 @@ class TestCache(unittest.TestCase):
|
|||
rmtree(self.temp_cache)
|
||||
|
||||
def _get_cache_enabled_settings(self):
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['CACHE_CONTENT'] = True
|
||||
settings['LOAD_CONTENT_CACHE'] = True
|
||||
settings['CACHE_PATH'] = self.temp_cache
|
||||
|
|
@ -42,20 +42,21 @@ class TestCache(unittest.TestCase):
|
|||
settings['PAGE_PATHS'] = ['TestPages']
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
settings['READERS'] = {'asc': None}
|
||||
context = get_context(settings)
|
||||
|
||||
def sorted_titles(items):
|
||||
return sorted(item.title for item in items)
|
||||
|
||||
# Articles
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
uncached_articles = sorted_titles(generator.articles)
|
||||
uncached_drafts = sorted_titles(generator.drafts)
|
||||
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
cached_articles = sorted_titles(generator.articles)
|
||||
|
|
@ -66,7 +67,7 @@ class TestCache(unittest.TestCase):
|
|||
|
||||
# Pages
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
uncached_pages = sorted_titles(generator.pages)
|
||||
|
|
@ -74,7 +75,7 @@ class TestCache(unittest.TestCase):
|
|||
uncached_draft_pages = sorted_titles(generator.draft_pages)
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
cached_pages = sorted_titles(generator.pages)
|
||||
|
|
@ -92,20 +93,21 @@ class TestCache(unittest.TestCase):
|
|||
settings['PAGE_PATHS'] = ['TestPages']
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
settings['READERS'] = {'asc': None}
|
||||
context = get_context(settings)
|
||||
|
||||
def sorted_titles(items):
|
||||
return sorted(item.title for item in items)
|
||||
|
||||
# Articles
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
uncached_articles = sorted_titles(generator.articles)
|
||||
uncached_drafts = sorted_titles(generator.drafts)
|
||||
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
cached_articles = sorted_titles(generator.articles)
|
||||
|
|
@ -116,14 +118,14 @@ class TestCache(unittest.TestCase):
|
|||
|
||||
# Pages
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
uncached_pages = sorted_titles(generator.pages)
|
||||
uncached_hidden_pages = sorted_titles(generator.hidden_pages)
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
cached_pages = sorted_titles(generator.pages)
|
||||
|
|
@ -139,15 +141,16 @@ class TestCache(unittest.TestCase):
|
|||
settings['CONTENT_CACHING_LAYER'] = 'generator'
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
settings['READERS'] = {'asc': None}
|
||||
context = get_context(settings)
|
||||
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
self.assertTrue(hasattr(generator, '_cache'))
|
||||
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.readers.read_file = MagicMock()
|
||||
generator.generate_context()
|
||||
|
|
@ -167,15 +170,16 @@ class TestCache(unittest.TestCase):
|
|||
"""Test raw article content caching at the reader level"""
|
||||
settings = self._get_cache_enabled_settings()
|
||||
settings['READERS'] = {'asc': None}
|
||||
context = get_context(settings)
|
||||
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
self.assertTrue(hasattr(generator.readers, '_cache'))
|
||||
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
readers = generator.readers.readers
|
||||
for reader in readers.values():
|
||||
|
|
@ -191,9 +195,10 @@ class TestCache(unittest.TestCase):
|
|||
used in --ignore-cache or autoreload mode"""
|
||||
settings = self._get_cache_enabled_settings()
|
||||
settings['READERS'] = {'asc': None}
|
||||
context = get_context(settings)
|
||||
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.readers.read_file = MagicMock()
|
||||
generator.generate_context()
|
||||
|
|
@ -202,7 +207,7 @@ class TestCache(unittest.TestCase):
|
|||
|
||||
settings['LOAD_CONTENT_CACHE'] = False
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.readers.read_file = MagicMock()
|
||||
generator.generate_context()
|
||||
|
|
@ -217,15 +222,16 @@ class TestCache(unittest.TestCase):
|
|||
settings['CONTENT_CACHING_LAYER'] = 'generator'
|
||||
settings['PAGE_PATHS'] = ['TestPages']
|
||||
settings['READERS'] = {'asc': None}
|
||||
context = get_context(settings)
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
self.assertTrue(hasattr(generator, '_cache'))
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.readers.read_file = MagicMock()
|
||||
generator.generate_context()
|
||||
|
|
@ -241,15 +247,16 @@ class TestCache(unittest.TestCase):
|
|||
settings = self._get_cache_enabled_settings()
|
||||
settings['PAGE_PATHS'] = ['TestPages']
|
||||
settings['READERS'] = {'asc': None}
|
||||
context = get_context(settings)
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
self.assertTrue(hasattr(generator.readers, '_cache'))
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
readers = generator.readers.readers
|
||||
for reader in readers.values():
|
||||
|
|
@ -266,9 +273,10 @@ class TestCache(unittest.TestCase):
|
|||
settings = self._get_cache_enabled_settings()
|
||||
settings['PAGE_PATHS'] = ['TestPages']
|
||||
settings['READERS'] = {'asc': None}
|
||||
context = get_context(settings)
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.readers.read_file = MagicMock()
|
||||
generator.generate_context()
|
||||
|
|
@ -277,7 +285,7 @@ class TestCache(unittest.TestCase):
|
|||
|
||||
settings['LOAD_CONTENT_CACHE'] = False
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.readers.read_file = MagicMock()
|
||||
generator.generate_context()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ import six
|
|||
from pelican.contents import Article, Author, Category, Page, Static, Tag
|
||||
from pelican.settings import DEFAULT_CONFIG
|
||||
from pelican.signals import content_object_init
|
||||
from pelican.tests.support import LoggedTestCase, get_settings, unittest
|
||||
from pelican.tests.support import LoggedTestCase, get_context, get_settings,\
|
||||
unittest
|
||||
from pelican.utils import SafeDatetime, path_to_url, truncate_html_words
|
||||
|
||||
|
||||
|
|
@ -264,7 +265,7 @@ class TestPage(LoggedTestCase):
|
|||
args = self.page_kwargs.copy()
|
||||
args['settings'] = get_settings()
|
||||
args['source_path'] = 'content'
|
||||
args['context']['filenames'] = {'article.rst': article}
|
||||
args['context']['generated_content'] = {'article.rst': article}
|
||||
|
||||
# Classic intrasite link via filename
|
||||
args['content'] = (
|
||||
|
|
@ -343,22 +344,24 @@ class TestPage(LoggedTestCase):
|
|||
args = self.page_kwargs.copy()
|
||||
args['settings'] = get_settings()
|
||||
args['source_path'] = 'content'
|
||||
args['context']['filenames'] = {
|
||||
'images/poster.jpg': type(
|
||||
cls_name, (object,), {'url': 'images/poster.jpg'}),
|
||||
'assets/video.mp4': type(
|
||||
cls_name, (object,), {'url': 'assets/video.mp4'}),
|
||||
'images/graph.svg': type(
|
||||
cls_name, (object,), {'url': 'images/graph.svg'}),
|
||||
'reference.rst': type(
|
||||
cls_name, (object,), {'url': 'reference.html'}),
|
||||
args['context']['static_content'] = {
|
||||
'images/poster.jpg':
|
||||
type(cls_name, (object,), {'url': 'images/poster.jpg'}),
|
||||
'assets/video.mp4':
|
||||
type(cls_name, (object,), {'url': 'assets/video.mp4'}),
|
||||
'images/graph.svg':
|
||||
type(cls_name, (object,), {'url': 'images/graph.svg'}),
|
||||
}
|
||||
args['context']['generated_content'] = {
|
||||
'reference.rst':
|
||||
type(cls_name, (object,), {'url': 'reference.html'}),
|
||||
}
|
||||
|
||||
# video.poster
|
||||
args['content'] = (
|
||||
'There is a video with poster '
|
||||
'<video controls poster="{filename}/images/poster.jpg">'
|
||||
'<source src="|filename|/assets/video.mp4" type="video/mp4">'
|
||||
'<video controls poster="{static}/images/poster.jpg">'
|
||||
'<source src="|static|/assets/video.mp4" type="video/mp4">'
|
||||
'</video>'
|
||||
)
|
||||
content = Page(**args).get_content('http://notmyidea.org')
|
||||
|
|
@ -374,7 +377,7 @@ class TestPage(LoggedTestCase):
|
|||
# object.data
|
||||
args['content'] = (
|
||||
'There is a svg object '
|
||||
'<object data="{filename}/images/graph.svg"'
|
||||
'<object data="{static}/images/graph.svg"'
|
||||
' type="image/svg+xml">'
|
||||
'</object>'
|
||||
)
|
||||
|
|
@ -409,14 +412,15 @@ class TestPage(LoggedTestCase):
|
|||
STATIC_URL='http://static.cool.site/{path}',
|
||||
ARTICLE_URL='http://blog.cool.site/{slug}.html')
|
||||
args['source_path'] = 'content'
|
||||
args['context']['filenames'] = {
|
||||
'images/poster.jpg': Static('',
|
||||
settings=args['settings'],
|
||||
source_path='images/poster.jpg'),
|
||||
'article.rst': Article('',
|
||||
settings=args['settings'],
|
||||
metadata={'slug': 'article',
|
||||
'title': 'Article'})
|
||||
args['context']['static_content'] = {
|
||||
'images/poster.jpg':
|
||||
Static('', settings=args['settings'],
|
||||
source_path='images/poster.jpg'),
|
||||
}
|
||||
args['context']['generated_content'] = {
|
||||
'article.rst':
|
||||
Article('', settings=args['settings'], metadata={
|
||||
'slug': 'article', 'title': 'Article'})
|
||||
}
|
||||
|
||||
# Article link will go to blog
|
||||
|
|
@ -441,7 +445,7 @@ class TestPage(LoggedTestCase):
|
|||
|
||||
# Image link will go to static
|
||||
args['content'] = (
|
||||
'<img src="{filename}/images/poster.jpg"/>'
|
||||
'<img src="{static}/images/poster.jpg"/>'
|
||||
)
|
||||
content = Page(**args).get_content('http://cool.site')
|
||||
self.assertEqual(
|
||||
|
|
@ -458,7 +462,7 @@ class TestPage(LoggedTestCase):
|
|||
args = self.page_kwargs.copy()
|
||||
args['settings'] = get_settings()
|
||||
args['source_path'] = 'content'
|
||||
args['context']['filenames'] = {'article spaces.rst': article}
|
||||
args['context']['generated_content'] = {'article spaces.rst': article}
|
||||
|
||||
# An intrasite link via filename with %20 as a space
|
||||
args['content'] = (
|
||||
|
|
@ -472,6 +476,55 @@ class TestPage(LoggedTestCase):
|
|||
'<a href="http://notmyidea.org/article-spaces.html">link</a>'
|
||||
)
|
||||
|
||||
def test_intrasite_link_source_and_generated(self):
|
||||
"""Test linking both to the source and the generated article
|
||||
"""
|
||||
cls_name = '_DummyAsset' if six.PY3 else b'_DummyAsset'
|
||||
|
||||
args = self.page_kwargs.copy()
|
||||
args['settings'] = get_settings()
|
||||
args['source_path'] = 'content'
|
||||
args['context']['generated_content'] = {
|
||||
'article.rst': type(cls_name, (object,), {'url': 'article.html'})}
|
||||
args['context']['static_content'] = {
|
||||
'article.rst': type(cls_name, (object,), {'url': 'article.rst'})}
|
||||
|
||||
args['content'] = (
|
||||
'A simple test, with a link to an'
|
||||
'<a href="{filename}article.rst">article</a> and its'
|
||||
'<a href="{static}article.rst">source</a>'
|
||||
)
|
||||
content = Page(**args).get_content('http://notmyidea.org')
|
||||
self.assertEqual(
|
||||
content,
|
||||
'A simple test, with a link to an'
|
||||
'<a href="http://notmyidea.org/article.html">article</a> and its'
|
||||
'<a href="http://notmyidea.org/article.rst">source</a>'
|
||||
)
|
||||
|
||||
def test_intrasite_link_to_static_content_with_filename(self):
|
||||
"""Test linking to a static resource with deprecated {filename}
|
||||
"""
|
||||
cls_name = '_DummyAsset' if six.PY3 else b'_DummyAsset'
|
||||
|
||||
args = self.page_kwargs.copy()
|
||||
args['settings'] = get_settings()
|
||||
args['source_path'] = 'content'
|
||||
args['context']['static_content'] = {
|
||||
'poster.jpg':
|
||||
type(cls_name, (object,), {'url': 'images/poster.jpg'})}
|
||||
|
||||
args['content'] = (
|
||||
'A simple test, with a link to a'
|
||||
'<a href="{filename}poster.jpg">poster</a>'
|
||||
)
|
||||
content = Page(**args).get_content('http://notmyidea.org')
|
||||
self.assertEqual(
|
||||
content,
|
||||
'A simple test, with a link to a'
|
||||
'<a href="http://notmyidea.org/images/poster.jpg">poster</a>'
|
||||
)
|
||||
|
||||
def test_multiple_authors(self):
|
||||
"""Test article with multiple authors."""
|
||||
args = self.page_kwargs.copy()
|
||||
|
|
@ -599,13 +652,13 @@ class TestStatic(LoggedTestCase):
|
|||
STATIC_URL='{path}',
|
||||
PAGE_SAVE_AS=os.path.join('outpages', '{slug}.html'),
|
||||
PAGE_URL='outpages/{slug}.html')
|
||||
self.context = self.settings.copy()
|
||||
self.context = get_context(self.settings)
|
||||
|
||||
self.static = Static(content=None, metadata={}, settings=self.settings,
|
||||
source_path=posix_join('dir', 'foo.jpg'),
|
||||
context=self.context)
|
||||
|
||||
self.context['filenames'] = {self.static.source_path: self.static}
|
||||
self.context['static_content'][self.static.source_path] = self.static
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
|
@ -674,7 +727,7 @@ class TestStatic(LoggedTestCase):
|
|||
|
||||
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.)
|
||||
(For example, by a {static} link an a document processed earlier.)
|
||||
"""
|
||||
original_save_as = self.static.save_as
|
||||
|
||||
|
|
@ -690,7 +743,7 @@ class TestStatic(LoggedTestCase):
|
|||
|
||||
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.)
|
||||
(For example, by a {static} link an a document processed earlier.)
|
||||
"""
|
||||
original_url = self.static.url
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from tempfile import mkdtemp
|
|||
from pelican.generators import (ArticlesGenerator, Generator, PagesGenerator,
|
||||
PelicanTemplateNotFound, StaticGenerator,
|
||||
TemplatePagesGenerator)
|
||||
from pelican.tests.support import get_settings, unittest
|
||||
from pelican.tests.support import get_context, get_settings, unittest
|
||||
from pelican.writers import Writer
|
||||
|
||||
try:
|
||||
|
|
@ -178,14 +178,15 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['DEFAULT_CATEGORY'] = 'Default'
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
settings['READERS'] = {'asc': None}
|
||||
settings['CACHE_CONTENT'] = False
|
||||
context = get_context(settings)
|
||||
|
||||
cls.generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
cls.generator.generate_context()
|
||||
cls.articles = cls.distill_articles(cls.generator.articles)
|
||||
|
|
@ -299,15 +300,15 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
self.assertEqual(sorted(categories), sorted(categories_expected))
|
||||
|
||||
def test_do_not_use_folder_as_category(self):
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['DEFAULT_CATEGORY'] = 'Default'
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
settings['USE_FOLDER_AS_CATEGORY'] = False
|
||||
settings['CACHE_PATH'] = self.temp_cache
|
||||
settings['READERS'] = {'asc': None}
|
||||
settings['filenames'] = {}
|
||||
context = get_context(settings)
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
# test for name
|
||||
|
|
@ -328,15 +329,16 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
@unittest.skipUnless(MagicMock, 'Needs Mock module')
|
||||
def test_direct_templates_save_as_url_default(self):
|
||||
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['CACHE_PATH'] = self.temp_cache
|
||||
context = get_context(settings)
|
||||
generator = ArticlesGenerator(
|
||||
context=settings, settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=None, theme=settings['THEME'], output_path=None)
|
||||
write = MagicMock()
|
||||
generator.generate_direct_templates(write)
|
||||
write.assert_called_with("archives.html",
|
||||
generator.get_template("archives"), settings,
|
||||
generator.get_template("archives"), context,
|
||||
articles=generator.articles,
|
||||
dates=generator.dates, blog=True,
|
||||
template_name='archives',
|
||||
|
|
@ -396,13 +398,14 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
"""
|
||||
old_locale = locale.setlocale(locale.LC_ALL)
|
||||
locale.setlocale(locale.LC_ALL, str('C'))
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
|
||||
settings['YEAR_ARCHIVE_SAVE_AS'] = 'posts/{date:%Y}/index.html'
|
||||
settings['YEAR_ARCHIVE_URL'] = 'posts/{date:%Y}/'
|
||||
settings['CACHE_PATH'] = self.temp_cache
|
||||
context = get_context(settings)
|
||||
generator = ArticlesGenerator(
|
||||
context=settings, settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
write = MagicMock()
|
||||
|
|
@ -411,20 +414,20 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
articles = [d for d in generator.articles if d.date.year == 1970]
|
||||
self.assertEqual(len(dates), 1)
|
||||
# among other things it must have at least been called with this
|
||||
settings["period"] = (1970,)
|
||||
context["period"] = (1970,)
|
||||
write.assert_called_with("posts/1970/index.html",
|
||||
generator.get_template("period_archives"),
|
||||
settings, blog=True, articles=articles,
|
||||
context, blog=True, articles=articles,
|
||||
dates=dates, template_name='period_archives',
|
||||
url="posts/1970/")
|
||||
|
||||
del settings["period"]
|
||||
settings['MONTH_ARCHIVE_SAVE_AS'] = \
|
||||
'posts/{date:%Y}/{date:%b}/index.html'
|
||||
settings['MONTH_ARCHIVE_URL'] = \
|
||||
'posts/{date:%Y}/{date:%b}/'
|
||||
context = get_context(settings)
|
||||
generator = ArticlesGenerator(
|
||||
context=settings, settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
write = MagicMock()
|
||||
|
|
@ -434,21 +437,21 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
articles = [d for d in generator.articles
|
||||
if d.date.year == 1970 and d.date.month == 1]
|
||||
self.assertEqual(len(dates), 1)
|
||||
settings["period"] = (1970, "January")
|
||||
context["period"] = (1970, "January")
|
||||
# among other things it must have at least been called with this
|
||||
write.assert_called_with("posts/1970/Jan/index.html",
|
||||
generator.get_template("period_archives"),
|
||||
settings, blog=True, articles=articles,
|
||||
context, blog=True, articles=articles,
|
||||
dates=dates, template_name='period_archives',
|
||||
url="posts/1970/Jan/")
|
||||
|
||||
del settings["period"]
|
||||
settings['DAY_ARCHIVE_SAVE_AS'] = \
|
||||
'posts/{date:%Y}/{date:%b}/{date:%d}/index.html'
|
||||
settings['DAY_ARCHIVE_URL'] = \
|
||||
'posts/{date:%Y}/{date:%b}/{date:%d}/'
|
||||
context = get_context(settings)
|
||||
generator = ArticlesGenerator(
|
||||
context=settings, settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
write = MagicMock()
|
||||
|
|
@ -466,20 +469,21 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
d.date.day == 1
|
||||
]
|
||||
self.assertEqual(len(dates), 1)
|
||||
settings["period"] = (1970, "January", 1)
|
||||
context["period"] = (1970, "January", 1)
|
||||
# among other things it must have at least been called with this
|
||||
write.assert_called_with("posts/1970/Jan/01/index.html",
|
||||
generator.get_template("period_archives"),
|
||||
settings, blog=True, articles=articles,
|
||||
context, blog=True, articles=articles,
|
||||
dates=dates, template_name='period_archives',
|
||||
url="posts/1970/Jan/01/")
|
||||
locale.setlocale(locale.LC_ALL, old_locale)
|
||||
|
||||
def test_nonexistent_template(self):
|
||||
"""Attempt to load a non-existent template"""
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
context = get_context(settings)
|
||||
generator = ArticlesGenerator(
|
||||
context=settings, settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=None, theme=settings['THEME'], output_path=None)
|
||||
self.assertRaises(Exception, generator.get_template, "not_a_template")
|
||||
|
||||
|
|
@ -497,7 +501,7 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
self.assertEqual(sorted(authors), sorted(authors_expected))
|
||||
|
||||
def test_standard_metadata_in_default_metadata(self):
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['CACHE_CONTENT'] = False
|
||||
settings['DEFAULT_CATEGORY'] = 'Default'
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
|
|
@ -506,8 +510,9 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
# DEFAULT_CATEGORY
|
||||
('category', 'Random'),
|
||||
('tags', 'general, untagged'))
|
||||
context = get_context(settings)
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
|
||||
|
|
@ -530,13 +535,14 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
self.assertEqual(tags, tags_expected)
|
||||
|
||||
def test_article_order_by(self):
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['DEFAULT_CATEGORY'] = 'Default'
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
settings['ARTICLE_ORDER_BY'] = 'title'
|
||||
context = get_context(settings)
|
||||
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
|
||||
|
|
@ -575,13 +581,14 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
self.assertEqual(articles, expected)
|
||||
|
||||
# reversed title
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['DEFAULT_CATEGORY'] = 'Default'
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
settings['ARTICLE_ORDER_BY'] = 'reversed-title'
|
||||
context = get_context(settings)
|
||||
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
|
||||
|
|
@ -605,13 +612,14 @@ class TestPageGenerator(unittest.TestCase):
|
|||
return [[page.title, page.status, page.template] for page in pages]
|
||||
|
||||
def test_generate_context(self):
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['CACHE_PATH'] = self.temp_cache
|
||||
settings['PAGE_PATHS'] = ['TestPages'] # relative to CUR_DIR
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
context = get_context(settings)
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
pages = self.distill_pages(generator.pages)
|
||||
|
|
@ -624,6 +632,7 @@ class TestPageGenerator(unittest.TestCase):
|
|||
['This is a test page with a preset template', 'published',
|
||||
'custom'],
|
||||
['Page with a bunch of links', 'published', 'page'],
|
||||
['Page with static links', 'published', 'page'],
|
||||
['A Page (Test) for sorting', 'published', 'page'],
|
||||
]
|
||||
hidden_pages_expected = [
|
||||
|
|
@ -653,10 +662,11 @@ class TestPageGenerator(unittest.TestCase):
|
|||
sorted(self.distill_pages(generator.context['draft_pages'])))
|
||||
|
||||
def test_generate_sorted(self):
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['PAGE_PATHS'] = ['TestPages'] # relative to CUR_DIR
|
||||
settings['CACHE_PATH'] = self.temp_cache
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
context = get_context(settings)
|
||||
|
||||
# default sort (filename)
|
||||
pages_expected_sorted_by_filename = [
|
||||
|
|
@ -664,11 +674,12 @@ class TestPageGenerator(unittest.TestCase):
|
|||
['This is a markdown test page', 'published', 'page'],
|
||||
['A Page (Test) for sorting', 'published', 'page'],
|
||||
['Page with a bunch of links', 'published', 'page'],
|
||||
['Page with static links', 'published', 'page'],
|
||||
['This is a test page with a preset template', 'published',
|
||||
'custom'],
|
||||
]
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
pages = self.distill_pages(generator.pages)
|
||||
|
|
@ -678,14 +689,16 @@ class TestPageGenerator(unittest.TestCase):
|
|||
pages_expected_sorted_by_title = [
|
||||
['A Page (Test) for sorting', 'published', 'page'],
|
||||
['Page with a bunch of links', 'published', 'page'],
|
||||
['Page with static 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',
|
||||
'custom'],
|
||||
]
|
||||
settings['PAGE_ORDER_BY'] = 'title'
|
||||
context = get_context(settings)
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context.copy(), settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
pages = self.distill_pages(generator.pages)
|
||||
|
|
@ -697,12 +710,14 @@ class TestPageGenerator(unittest.TestCase):
|
|||
'custom'],
|
||||
['This is a test page', 'published', 'page'],
|
||||
['This is a markdown test page', 'published', 'page'],
|
||||
['Page with static links', 'published', 'page'],
|
||||
['Page with a bunch of links', 'published', 'page'],
|
||||
['A Page (Test) for sorting', 'published', 'page'],
|
||||
]
|
||||
settings['PAGE_ORDER_BY'] = 'reversed-title'
|
||||
context = get_context(settings)
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context, settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
pages = self.distill_pages(generator.pages)
|
||||
|
|
@ -713,21 +728,43 @@ class TestPageGenerator(unittest.TestCase):
|
|||
Test to ensure links of the form {tag}tagname and {category}catname
|
||||
are generated correctly on pages
|
||||
"""
|
||||
settings = get_settings(filenames={})
|
||||
settings = get_settings()
|
||||
settings['PAGE_PATHS'] = ['TestPages'] # relative to CUR_DIR
|
||||
settings['CACHE_PATH'] = self.temp_cache
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
context = get_context(settings)
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
context=context, 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}
|
||||
pages_by_title = {p.title: p for p in generator.pages}
|
||||
|
||||
test_content = pages_by_title['Page with a bunch of links']
|
||||
test_content = pages_by_title['Page with a bunch of links'].content
|
||||
self.assertIn('<a href="/category/yeah.html">', test_content)
|
||||
self.assertIn('<a href="/tag/matsuku.html">', test_content)
|
||||
|
||||
def test_static_and_attach_links_on_generated_pages(self):
|
||||
"""
|
||||
Test to ensure links of the form {static}filename and {attach}filename
|
||||
are included in context['static_links']
|
||||
"""
|
||||
settings = get_settings()
|
||||
settings['PAGE_PATHS'] = ['TestPages/page_with_static_links.md']
|
||||
settings['CACHE_PATH'] = self.temp_cache
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
context = get_context(settings)
|
||||
|
||||
generator = PagesGenerator(
|
||||
context=context, settings=settings,
|
||||
path=CUR_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
|
||||
self.assertIn('pelican/tests/TestPages/image0.jpg',
|
||||
context['static_links'])
|
||||
self.assertIn('pelican/tests/TestPages/image1.jpg',
|
||||
context['static_links'])
|
||||
|
||||
|
||||
class TestTemplatePagesGenerator(unittest.TestCase):
|
||||
|
||||
|
|
@ -791,7 +828,7 @@ class TestStaticGenerator(unittest.TestCase):
|
|||
"static", "staticfile")
|
||||
self.endfile = os.path.join(self.temp_output, "static", "staticfile")
|
||||
self.generator = StaticGenerator(
|
||||
context={'filenames': {}},
|
||||
context=get_context(),
|
||||
settings=self.settings,
|
||||
path=self.temp_content,
|
||||
theme="",
|
||||
|
|
@ -808,11 +845,8 @@ class TestStaticGenerator(unittest.TestCase):
|
|||
def test_theme_static_paths_dirs(self):
|
||||
"""Test that StaticGenerator properly copies also files mentioned in
|
||||
TEMPLATE_STATIC_PATHS, not just directories."""
|
||||
settings = get_settings(
|
||||
PATH=self.content_path,
|
||||
filenames={})
|
||||
context = settings.copy()
|
||||
context['staticfiles'] = []
|
||||
settings = get_settings(PATH=self.content_path)
|
||||
context = get_context(settings, staticfiles=[])
|
||||
|
||||
StaticGenerator(
|
||||
context=context, settings=settings,
|
||||
|
|
@ -831,10 +865,8 @@ class TestStaticGenerator(unittest.TestCase):
|
|||
TEMPLATE_STATIC_PATHS, not just directories."""
|
||||
settings = get_settings(
|
||||
PATH=self.content_path,
|
||||
THEME_STATIC_PATHS=['static/css/fonts.css', 'static/fonts/'],
|
||||
filenames={})
|
||||
context = settings.copy()
|
||||
context['staticfiles'] = []
|
||||
THEME_STATIC_PATHS=['static/css/fonts.css', 'static/fonts/'],)
|
||||
context = get_context(settings, staticfiles=[])
|
||||
|
||||
StaticGenerator(
|
||||
context=context, settings=settings,
|
||||
|
|
@ -869,9 +901,8 @@ class TestStaticGenerator(unittest.TestCase):
|
|||
settings = get_settings(
|
||||
STATIC_EXCLUDES=['subdir'],
|
||||
PATH=self.content_path,
|
||||
STATIC_PATHS=[''],
|
||||
filenames={})
|
||||
context = settings.copy()
|
||||
STATIC_PATHS=[''],)
|
||||
context = get_context(settings)
|
||||
|
||||
StaticGenerator(
|
||||
context=context, settings=settings,
|
||||
|
|
@ -897,9 +928,8 @@ class TestStaticGenerator(unittest.TestCase):
|
|||
PATH=self.content_path,
|
||||
PAGE_PATHS=[''],
|
||||
STATIC_PATHS=[''],
|
||||
CACHE_CONTENT=False,
|
||||
filenames={})
|
||||
context = settings.copy()
|
||||
CACHE_CONTENT=False,)
|
||||
context = get_context(settings)
|
||||
|
||||
for generator_class in (PagesGenerator, StaticGenerator):
|
||||
generator_class(
|
||||
|
|
@ -915,8 +945,7 @@ class TestStaticGenerator(unittest.TestCase):
|
|||
"STATIC_EXCLUDE_SOURCES=True failed to exclude a markdown file")
|
||||
|
||||
settings.update(STATIC_EXCLUDE_SOURCES=False)
|
||||
context = settings.copy()
|
||||
context['filenames'] = {}
|
||||
context = get_context(settings)
|
||||
|
||||
for generator_class in (PagesGenerator, StaticGenerator):
|
||||
generator_class(
|
||||
|
|
@ -931,6 +960,40 @@ class TestStaticGenerator(unittest.TestCase):
|
|||
any(name.endswith(".md") for name in staticnames),
|
||||
"STATIC_EXCLUDE_SOURCES=False failed to include a markdown file")
|
||||
|
||||
def test_static_links(self):
|
||||
"""Test that StaticGenerator uses files in static_links
|
||||
"""
|
||||
settings = get_settings(
|
||||
STATIC_EXCLUDES=['subdir'],
|
||||
PATH=self.content_path,
|
||||
STATIC_PATHS=[],)
|
||||
context = get_context(settings)
|
||||
context['static_links'] |= {'short_page.md', 'subdir_fake_image.jpg'}
|
||||
|
||||
StaticGenerator(
|
||||
context=context, settings=settings,
|
||||
path=settings['PATH'], output_path=self.temp_output,
|
||||
theme=settings['THEME']).generate_context()
|
||||
|
||||
staticfiles_names = [
|
||||
os.path.basename(c.source_path) for c in context['staticfiles']]
|
||||
|
||||
static_content_names = [
|
||||
os.path.basename(c) for c in context['static_content']]
|
||||
|
||||
self.assertIn(
|
||||
'short_page.md', staticfiles_names,
|
||||
"StaticGenerator skipped a file that it should have included")
|
||||
self.assertIn(
|
||||
'short_page.md', static_content_names,
|
||||
"StaticGenerator skipped a file that it should have included")
|
||||
self.assertIn(
|
||||
'subdir_fake_image.jpg', staticfiles_names,
|
||||
"StaticGenerator skipped a file that it should have included")
|
||||
self.assertIn(
|
||||
'subdir_fake_image.jpg', static_content_names,
|
||||
"StaticGenerator skipped a file that it should have included")
|
||||
|
||||
def test_copy_one_file(self):
|
||||
with open(self.startfile, "w") as f:
|
||||
f.write("staticcontent")
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class TestPelican(LoggedTestCase):
|
|||
self.assertDirsEqual(
|
||||
self.temp_path, os.path.join(OUTPUT_PATH, 'basic'))
|
||||
self.assertLogCountEqual(
|
||||
count=3,
|
||||
count=1,
|
||||
msg="Unable to find.*skipping url replacement",
|
||||
level=logging.WARNING)
|
||||
|
||||
|
|
|
|||
|
|
@ -761,7 +761,7 @@ def update_links_to_attached_files(content, attachments):
|
|||
http_url = old_url.replace('https://', 'http://')
|
||||
https_url = old_url.replace('http://', 'https://')
|
||||
for url in [http_url, https_url]:
|
||||
content = content.replace(url, '{filename}' + new_path)
|
||||
content = content.replace(url, '{static}' + new_path)
|
||||
return content
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ def path_to_url(path):
|
|||
|
||||
def posixize_path(rel_path):
|
||||
"""Use '/' as path separator, so that source references,
|
||||
like '{filename}/foo/bar.jpg' or 'extras/favicon.ico',
|
||||
like '{static}/foo/bar.jpg' or 'extras/favicon.ico',
|
||||
will work on Windows as well as on Mac and Linux."""
|
||||
return rel_path.replace(os.sep, '/')
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Why not ?
|
|||
After all, why not ? It's pretty simple to do it, and it will allow me to write my blogposts in rst !
|
||||
YEAH !
|
||||
|
||||
.. image:: |filename|/pictures/Sushi.jpg
|
||||
.. image:: |static|/pictures/Sushi.jpg
|
||||
:height: 450 px
|
||||
:width: 600 px
|
||||
:alt: alternate text
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ This is a simple title
|
|||
|
||||
And here comes the cool stuff_.
|
||||
|
||||
.. image:: |filename|/pictures/Sushi.jpg
|
||||
.. image:: |static|/pictures/Sushi.jpg
|
||||
:height: 450 px
|
||||
:width: 600 px
|
||||
:alt: alternate text
|
||||
|
||||
.. image:: |filename|/pictures/Sushi_Macro.jpg
|
||||
.. image:: |static|/pictures/Sushi_Macro.jpg
|
||||
:height: 450 px
|
||||
:width: 600 px
|
||||
:alt: alternate text
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue