chiark / gitweb /
theme: properly HTML-escape all content and test the results.
authorVladimír Vondruš <mosra@centrum.cz>
Sun, 10 Dec 2017 23:39:11 +0000 (00:39 +0100)
committerVladimír Vondruš <mosra@centrum.cz>
Mon, 11 Dec 2017 01:48:25 +0000 (02:48 +0100)
35 files changed:
pelican-theme/templates/archives.html
pelican-theme/templates/article.html
pelican-theme/templates/article_header.html
pelican-theme/templates/author.html
pelican-theme/templates/base.html
pelican-theme/templates/base_blog.html
pelican-theme/templates/base_blog_section.html
pelican-theme/templates/category.html
pelican-theme/templates/page.html
pelican-theme/templates/pagination.html
pelican-theme/templates/tag.html
pelican-theme/test/blog_html_escape/article-jumbo.html [new file with mode: 0644]
pelican-theme/test/blog_html_escape/article-jumbo.rst [new file with mode: 0644]
pelican-theme/test/blog_html_escape/article.html [new file with mode: 0644]
pelican-theme/test/blog_html_escape/article.rst [new file with mode: 0644]
pelican-theme/test/blog_html_escape/author-and-in-author.html [new file with mode: 0644]
pelican-theme/test/blog_html_escape/author-and-in-author2.html [new file with mode: 0644]
pelican-theme/test/blog_html_escape/category-and-in-category.html [new file with mode: 0644]
pelican-theme/test/blog_html_escape/category-and-in-category2.html [new file with mode: 0644]
pelican-theme/test/blog_html_escape/index.html [new file with mode: 0644]
pelican-theme/test/blog_html_escape/index2.html [new file with mode: 0644]
pelican-theme/test/blog_html_escape/tag-and-in-tag.html [new file with mode: 0644]
pelican-theme/test/blog_html_escape/tag-and-in-tag2.html [new file with mode: 0644]
pelican-theme/test/layout_html_escape/index.html [new file with mode: 0644]
pelican-theme/test/page_html_escape/breadcrumb.html [new file with mode: 0644]
pelican-theme/test/page_html_escape/breadcrumb.rst [new file with mode: 0644]
pelican-theme/test/page_html_escape/content.html [new file with mode: 0644]
pelican-theme/test/page_html_escape/content.rst [new file with mode: 0644]
pelican-theme/test/page_html_escape/landing.html [new file with mode: 0644]
pelican-theme/test/page_html_escape/landing.rst [new file with mode: 0644]
pelican-theme/test/page_html_escape/page.html [new file with mode: 0644]
pelican-theme/test/page_html_escape/page.rst [new file with mode: 0644]
pelican-theme/test/test_blog.py
pelican-theme/test/test_layout.py
pelican-theme/test/test_page.py

index bcafc4ec412ebf0c60630857beffa1d08bedf5e2..41b7610901440e48a55a38fbbc7eac648d8792ef 100644 (file)
@@ -2,10 +2,10 @@
 
 {% block head_links %}
   {% if articles_page and articles_page.has_previous() %}
-  <link rel="prev" href="{{ articles_previous_page.url|format_siteurl }}" />
+  <link rel="prev" href="{{ articles_previous_page.url|format_siteurl|e }}" />
   {% endif %}
   {% if articles_page and articles_page.has_next() %}
-  <link rel="next" href="{{ articles_next_page.url|format_siteurl }}" />
+  <link rel="next" href="{{ articles_next_page.url|format_siteurl|e }}" />
   {% endif %}
 {% endblock head_links %}
 
index 03bcc708bcbaa601e6e54e021c735f4ca6ce26c3..49b4b221d9d5716643e7babed1b3059487209cdf 100644 (file)
@@ -1,25 +1,25 @@
 {% extends "base_blog.html" %}
 
-{% block title %}{{ article.title }} | {{ M_BLOG_NAME }}{% endblock %}
+{% block title %}{{ article.title }} | {{ M_BLOG_NAME|e }}{% endblock %}
 
 {% block head %}
   {{- super() -}}
   {% if article.description %}
-  <meta name="description" content="{{ article.description }}" />
+  <meta name="description" content="{{ article.description|striptags|e }}" />
   {% endif %}
-  <meta name="keywords" content="{{ article.tags|join(", ") }}" />
+  <meta name="keywords" content="{{ article.tags|join(', ')|e }}" />
   <meta property="og:title" content="{{ article.title }}" />
   <meta name="twitter:title" content="{{ article.title }}" />
-  <meta property="og:url" content="{{ article.url|format_siteurl }}" />
-  <meta name="twitter:url" content="{{ article.url|format_siteurl }}" />
+  <meta property="og:url" content="{{ article.url|format_siteurl|e }}" />
+  <meta name="twitter:url" content="{{ article.url|format_siteurl|e }}" />
   {% if article.summary %}
-  <meta property="og:description" content="{{ article.summary|striptags }}" />
-  <meta name="twitter:description" content="{{ article.summary|striptags }}" />
+  <meta property="og:description" content="{{ article.summary|striptags|e }}" />
+  <meta name="twitter:description" content="{{ article.summary|striptags|e }}" />
   {% endif %}
   {% if article.cover %}
-  <meta property="og:image" content="{{ article.cover|expand_link(article) }}" />
+  <meta property="og:image" content="{{ article.cover|expand_link(article)|e }}" />
   <meta name="twitter:card" content="summary_large_image" />
-  <meta name="twitter:image" content="{{ article.cover|expand_link(article) }}" />
+  <meta name="twitter:image" content="{{ article.cover|expand_link(article)|e }}" />
   {% else %}
   <meta name="twitter:card" content="summary" />
   {% endif %}
 
 {% block content %}
   {% if article.cover %}
-  <article id="m-jumbo"{% if article.class %}class="{{ article.class }}"{%endif%}">
+  <article id="m-jumbo"{% if article.class %} class="{{ article.class }}"{% endif %}>
     <header>
-      <div id="m-jumbo-image" style="background-image: url('{{ article.cover|expand_link(article) }}');">
+      <div id="m-jumbo-image" style="background-image: url('{{ article.cover|expand_link(article)|e }}');">
         <div id="m-jumbo-cover">
           <div class="m-container">
             <div class="m-row">
-              <div class="{% if article.authors %}m-col-t-6 m-col-s-5{% else %}m-col-t-12 m-col-s-10{% endif %} m-push-s-1 m-text-left">{{ article.locale_date }}</div>
+              <div class="{% if article.authors %}m-col-t-6 m-col-s-5{% else %}m-col-t-12 m-col-s-10{% endif %} m-push-s-1 m-text-left">{{ article.locale_date|e }}</div>
               {% if article.authors %}
-              <div class="m-col-t-6 m-col-s-5 m-push-s-1 m-text-right">{% for author in article.authors %}<a href="{{ author.url|format_siteurl }}">{{ author }}</a>{% endfor %}</div>
+              <div class="m-col-t-6 m-col-s-5 m-push-s-1 m-text-right">{% for author in article.authors %}<a href="{{ author.url|format_siteurl|e }}">{{ author|e }}</a>{% endfor %}</div>
               {% endif %}
             </div>
             <div class="m-row">
               <div class="m-col-t-12 m-col-s-10 m-push-s-1 m-col-m-8 m-push-m-2">
                 {% set title = article.title.split(' — ') %}
-                <h1><a href="{{ article.url|format_siteurl }}" rel="bookmark" title="Permalink to {{ article.title }}">{{ title[0] }}</a></h1>
+                <h1><a href="{{ article.url|format_siteurl|e }}" rel="bookmark" title="Permalink to {{ article.title }}">{{ title[0] }}</a></h1>
                 {% if title|length >= 2 %}
                 <h2>{{ title[1] }}</h2>
                 {% endif %}
index ba5d7847eb6aa1873bd8d4d96c954f8594d99dda..610762ad3a3e04dafabbe4afbfbff8747d6e1663 100644 (file)
@@ -1,5 +1,5 @@
 <header>
-  <h1><a href="{{ article.url|format_siteurl }}" rel="bookmark" title="Permalink to {{ article.title|striptags }}">
+  <h1><a href="{{ article.url|format_siteurl|e }}" rel="bookmark" title="Permalink to {{ article.title }}">
     <time class="m-date" datetime="{{ article.date.isoformat() }}">
       {% set month, day, year = article.date.strftime('%b %d %Y').split(' ') %}
       {{ month }} <span class="m-date-day">{{ day }}</span> {{year}}
index 45bb872e58a76625a88ec54a0d525ee6ceda2ad8..07b5e8c4cb84a3b9f8de04df7bcef5558b92ce62 100644 (file)
@@ -1,9 +1,9 @@
 {% extends "base_blog_section.html" %}
 
-{% block title %}Posts by {{ author }} | {{ M_BLOG_NAME }}{% endblock %}
+{% block title %}Posts by {{ author|e }} | {{ M_BLOG_NAME|e }}{% endblock %}
 
 {% block content_title %}
       <div class="m-info m-note">
-        Showing only posts by <em>{{ author }}</em>. <a href="{{ M_BLOG_URL|format_siteurl }}">Show all posts.</a>
+        Showing only posts by <em>{{ author|e }}</em>. <a href="{{ M_BLOG_URL|format_siteurl|e }}">Show all posts.</a>
       </div>
 {% endblock %}
index 70042623372dd2194cd78f8a11384e04547ca7e1..97a2bc0605f66bbddcc0c0cbe9a1ac009317c96d 100644 (file)
@@ -3,17 +3,17 @@
 <head>
   {% block head %}
   <meta charset="UTF-8" />
-  <title>{% block title %}{{ SITENAME }}{% endblock title %}</title>
+  <title>{% block title %}{{ SITENAME|e }}{% endblock title %}</title>
   {% for href in M_CSS_FILES %}
   <link rel="stylesheet" href="{{ href|format_siteurl|e }}" />
   {% endfor %}
   {% block head_links %}
   {% endblock head_links %}
   {% if FEED_ALL_ATOM_URL %}
-  <link href="{{ FEED_ALL_ATOM_URL|format_siteurl }}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }}" />
+  <link href="{{ FEED_ALL_ATOM_URL|format_siteurl|e }}" type="application/atom+xml" rel="alternate" title="{{ SITENAME|e }}" />
   {% endif %}
   {% if CATEGORY_FEED_ATOM_URL and category %}
-  <link href="{{ CATEGORY_FEED_ATOM_URL|format(category.slug)|format_siteurl }}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} | {{ category }}" />
+  <link href="{{ CATEGORY_FEED_ATOM_URL|format(category.slug)|format_siteurl }}" type="application/atom+xml" rel="alternate" title="{{ SITENAME|e }} | {{ category|e }}" />
   {% endif %}
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   {% if M_THEME_COLOR %}
@@ -26,8 +26,8 @@
   <div class="m-container">
     <div class="m-row">
       <a href="{{ SITEURL }}/" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m{% if page and page.landing and page.cover and page.hide_navbar_brand == 'True' %} m-navbar-brand-hidden{% endif %}">
-        {%- if M_SITE_LOGO %}<img src="{{ M_SITE_LOGO }}" />{% endif -%}
-        {{- M_SITE_LOGO_TEXT or SITENAME -}}
+        {%- if M_SITE_LOGO %}<img src="{{ M_SITE_LOGO|e }}" />{% endif -%}
+        {{- (M_SITE_LOGO_TEXT or SITENAME)|e -}}
       </a>
       {% if M_LINKS_NAVBAR1 or M_LINKS_NAVBAR2 %}
       <a id="m-navbar-show" href="#navigation" title="Show navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
           <ol class="{% if M_LINKS_NAVBAR2 %}m-col-t-6{% else %}m-col-t-12{% endif %} m-col-m-none">
             {% for title, link, slug, sub in M_LINKS_NAVBAR1 %}
             {% if not sub %}
-            <li><a href="{{ link|format_siteurl }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title }}</a></li>
+            <li><a href="{{ link|format_siteurl|e }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title|e }}</a></li>
             {% else %}
             <li>
-              <a href="{{ link|format_siteurl }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title }}</a>
+              <a href="{{ link|format_siteurl|e }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title|e }}</a>
               <ol>
                 {% for title, link, slug in sub %}
-                <li><a href="{{ link|format_siteurl }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title }}</a></li>
+                <li><a href="{{ link|format_siteurl|e }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title|e }}</a></li>
                 {% endfor %}
               </ol>
             </li>
           <ol class="m-col-t-6 m-col-m-none" start="{{ start }}">
             {% for title, link, slug, sub in M_LINKS_NAVBAR2 %}
             {% if not sub %}
-            <li><a href="{{ link|format_siteurl }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title }}</a></li>
+            <li><a href="{{ link|format_siteurl|e }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title|e }}</a></li>
             {% else %}
             <li>
-              <a href="{{ link|format_siteurl }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title }}</a>
+              <a href="{{ link|format_siteurl|e }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title|e }}</a>
               <ol>
                 {% for title, link, slug in sub %}
-                <li><a href="{{ link|format_siteurl }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title }}</a></li>
+                <li><a href="{{ link|format_siteurl|e }}"{% if (page and page.highlight == slug) or slug == page_slug %} id="m-navbar-current"{% endif %}>{{ title|e }}</a></li>
                 {% endfor %}
               </ol>
             </li>
       <div class="m-col-s-3 m-col-t-6">
         {% if M_LINKS_FOOTER1 %}
         <h3>
-          {%- if M_LINKS_FOOTER1[0][1] %}<a href="{{ M_LINKS_FOOTER1[0][1]|format_siteurl }}">{% endif %}
-          {{- M_LINKS_FOOTER1[0][0] -}}
+          {%- if M_LINKS_FOOTER1[0][1] %}<a href="{{ M_LINKS_FOOTER1[0][1]|format_siteurl|e }}">{% endif %}
+          {{- M_LINKS_FOOTER1[0][0]|e -}}
           {% if M_LINKS_FOOTER1[0][1] -%}</a>{% endif -%}
         </h3>
         <ul>
           {% for title, link in M_LINKS_FOOTER1 %}{% if loop.index0 != 0 %}
-          <li>{% if title %}<a href="{{ link|format_siteurl }}">{{ title }}</a>{% else %}&nbsp;{% endif %}</li>
+          <li>{% if title %}<a href="{{ link|format_siteurl|e }}">{{ title|e }}</a>{% else %}&nbsp;{% endif %}</li>
           {% endif %}{% endfor %}
         </ul>
         {% endif %}
       <div class="m-col-s-3 m-col-t-6">
         {% if M_LINKS_FOOTER2 %}
         <h3>
-          {%- if M_LINKS_FOOTER2[0][1] %}<a href="{{ M_LINKS_FOOTER2[0][1]|format_siteurl }}">{% endif %}
-          {{- M_LINKS_FOOTER2[0][0] -}}
+          {%- if M_LINKS_FOOTER2[0][1] %}<a href="{{ M_LINKS_FOOTER2[0][1]|format_siteurl|e }}">{% endif %}
+          {{- M_LINKS_FOOTER2[0][0]|e -}}
           {% if M_LINKS_FOOTER2[0][1] %}</a>{% endif -%}
         </h3>
         <ul>
           {% for title, link in M_LINKS_FOOTER2 %}{% if loop.index0 != 0 %}
-          <li>{% if title %}<a href="{{ link|format_siteurl }}">{{ title }}</a>{% else %}&nbsp;{% endif %}</li>
+          <li>{% if title %}<a href="{{ link|format_siteurl|e }}">{{ title|e }}</a>{% else %}&nbsp;{% endif %}</li>
           {% endif %}{% endfor %}
         </ul>
         {% endif %}
       <div class="m-col-s-3 m-col-t-6">
         {% if M_LINKS_FOOTER3 %}
         <h3>
-          {%- if M_LINKS_FOOTER3[0][1] %}<a href="{{ M_LINKS_FOOTER3[0][1]|format_siteurl }}">{% endif %}
-          {{- M_LINKS_FOOTER3[0][0] -}}
+          {%- if M_LINKS_FOOTER3[0][1] %}<a href="{{ M_LINKS_FOOTER3[0][1]|format_siteurl|e }}">{% endif %}
+          {{- M_LINKS_FOOTER3[0][0]|e -}}
           {% if M_LINKS_FOOTER3[0][1] %}</a>{% endif -%}
         </h3>
         <ul>
           {% for title, link in M_LINKS_FOOTER3 %}{% if loop.index0 != 0 %}
-          <li>{% if title %}<a href="{{ link|format_siteurl }}">{{ title }}</a>{% else %}&nbsp;{% endif %}</li>
+          <li>{% if title %}<a href="{{ link|format_siteurl|e }}">{{ title|e }}</a>{% else %}&nbsp;{% endif %}</li>
           {% endif %}{% endfor %}
         </ul>
         {% endif %}
       <div class="m-col-s-3 m-col-t-6">
         {% if M_LINKS_FOOTER4 %}
         <h3>
-          {%- if M_LINKS_FOOTER4[0][1] %}<a href="{{ M_LINKS_FOOTER4[0][1]|format_siteurl }}">{% endif %}
-          {{- M_LINKS_FOOTER4[0][0] -}}
+          {%- if M_LINKS_FOOTER4[0][1] %}<a href="{{ M_LINKS_FOOTER4[0][1]|format_siteurl|e }}">{% endif %}
+          {{- M_LINKS_FOOTER4[0][0]|e -}}
           {% if M_LINKS_FOOTER4[0][1] %}</a>{% endif -%}
         </h3>
         <ul>
           {% for title, link in M_LINKS_FOOTER4 %}{% if loop.index0 != 0 %}
-          <li>{% if title %}<a href="{{ link|format_siteurl }}">{{ title }}</a>{% else %}&nbsp;{% endif %}</li>
+          <li>{% if title %}<a href="{{ link|format_siteurl|e }}">{{ title|e }}</a>{% else %}&nbsp;{% endif %}</li>
           {% endif %}{% endfor %}
         </ul>
         {% elif M_LINKS_FOOTER4 is not defined %}
-        <h3><a href="{{ M_BLOG_URL|format_siteurl }}">Blog</a></h3>
+        <h3><a href="{{ M_BLOG_URL|format_siteurl|e }}">Blog</a></h3>
         <ul>
           {% for cat, null in categories %}
-          <li><a href="{{ cat.url|format_siteurl }}">{{ cat }}</a></li>
+          <li><a href="{{ cat.url|format_siteurl|e }}">{{ cat|e }}</a></li>
           {% endfor %}
         </ul>
         {% endif %}
index c867269634188478125aa73dc99cfeb10a1e23d5..81649628ce7c8ec43447dbdaf17281dd741690fc 100644 (file)
@@ -2,7 +2,7 @@
 {% if not M_BLOG_NAME %}{% set M_BLOG_NAME = SITENAME %}{% endif %}
 {% extends 'base.html' %}
 
-{% block title %}{{ M_BLOG_NAME }}{% endblock %}
+{% block title %}{{ M_BLOG_NAME|e }}{% endblock %}
 
 {% block main %}
 {% if article and article.cover %}
@@ -19,7 +19,7 @@
         <h3>{{ "Categories"|hyphenate(lang='en') }}</h3>
         <ol class="m-block-bar-s">
           {% for cat, null in categories %}
-          <li><a href="{{ cat.url|format_siteurl }}">{{ cat }}</a></li>
+          <li><a href="{{ cat.url|format_siteurl|e }}">{{ cat|e }}</a></li>
           {% endfor %}
         </ol>
       </div>
@@ -28,7 +28,7 @@
         <h3>{{ "Authors"|hyphenate(lang='en') }}</h3>
         <ol class="m-block-bar-s">
           {% for author, null in authors %}
-          <li><a href="{{ author.url|format_siteurl }}">{{ author }}</a></li>
+          <li><a href="{{ author.url|format_siteurl|e }}">{{ author|e }}</a></li>
           {% endfor %}
         </ol>
       </div>
@@ -39,7 +39,7 @@
         <ul class="m-tagcloud">
           {% set max_articles_per_tag = tags|map(attribute='1')|map('length')|sort|last %}
           {% for tag, articles in tags|sort(attribute='0') %}
-          <li class="m-tag-{{ (5*(articles|length)/max_articles_per_tag)|round(0, 'ceil')|int }}"><a href="{{ tag.url|format_siteurl }}">{{ tag }}</a></li>
+          <li class="m-tag-{{ (5*(articles|length)/max_articles_per_tag)|round(0, 'ceil')|int }}"><a href="{{ tag.url|format_siteurl|e }}">{{ tag|e }}</a></li>
           {% endfor %}
         </ul>
       </div>
         <li><em class="m-text m-dim">(none yet)</em></li>
         {% endif %}
         {% for cat, null in categories %}
-        <li><a href="{{ cat.url|format_siteurl }}">{{ cat|hyphenate }}</a></li>
+        <li><a href="{{ cat.url|format_siteurl|e }}">{{ cat|hyphenate|e }}</a></li>
         {% endfor %}
       </ol>
       {% if M_SHOW_AUTHOR_LIST and authors %}
       <h3>{{ "Authors"|hyphenate(lang='en') }}</h3>
       <ol class="m-block-bar-m">
         {% for author, null in authors %}
-        <li><a href="{{ author.url|format_siteurl }}">{{ author }}</a></li>
+        <li><a href="{{ author.url|format_siteurl|e }}">{{ author|e }}</a></li>
         {% endfor %}
       </ol>
       {% endif %}
@@ -70,7 +70,7 @@
       <ul class="m-tagcloud">
         {% set max_articles_per_tag = tags|map(attribute='1')|map('length')|sort|last %}
         {% for tag, articles in tags|sort(attribute='0') %}
-        <li class="m-tag-{{ (5*(articles|length)/max_articles_per_tag)|round(0, 'ceil')|int }}"><a href="{{ tag.url|format_siteurl }}">{{ tag }}</a></li>
+        <li class="m-tag-{{ (5*(articles|length)/max_articles_per_tag)|round(0, 'ceil')|int }}"><a href="{{ tag.url|format_siteurl|e }}">{{ tag|e }}</a></li>
         {% endfor %}
       </ul>
       {% endif %}
index 194aaf9f4fcb33eb4215df2f1c017b2b5340ec45..a4c71c4a3ffa7bb4f782d4b9d6757a09e0a55e72 100644 (file)
@@ -2,10 +2,10 @@
 
 {% block head_links %}
   {% if articles_page.has_previous() %}
-  <link rel="prev" href="{{ articles_previous_page.url|format_siteurl }}" />
+  <link rel="prev" href="{{ articles_previous_page.url|format_siteurl|e }}" />
   {% endif %}
   {% if articles_page.has_next() %}
-  <link rel="next" href="{{ articles_next_page.url|format_siteurl }}" />
+  <link rel="next" href="{{ articles_next_page.url|format_siteurl|e }}" />
   {% endif %}
 {% endblock head_links %}
 
index 8feae772f331927a11eef532939ac96c7b3c0a94..e7e4d2377849b949c51a42a0801917fe41dc5130 100644 (file)
@@ -1,9 +1,9 @@
 {% extends "base_blog_section.html" %}
 
-{% block title %}{{ category }} | {{ M_BLOG_NAME }}{% endblock %}
+{% block title %}{{ category|e }} | {{ M_BLOG_NAME|e }}{% endblock %}
 
 {% block content_title %}
       <div class="m-info m-note">
-        Showing only posts in <em>{{ category }}</em>. <a href="{{ M_BLOG_URL|format_siteurl }}">Show all posts.</a>
+        Showing only posts in <em>{{ category|e }}</em>. <a href="{{ M_BLOG_URL|format_siteurl|e }}">Show all posts.</a>
       </div>
 {% endblock %}
index 068e08c3a3303116bc7338859819cdc0a109b7ce..b7d3c9bccbbed7c053105dee6c9e2f26e2d9fd1d 100644 (file)
@@ -4,32 +4,32 @@
 {% block title %}
 {% if page.breadcrumb %}
 {% set breadcrumbs = page.breadcrumb.strip().split('\n') %}
-{% for i in breadcrumbs %}{% set url, _, title = i.strip().partition(' ') %}{{ title }} &raquo; {% endfor %}
+{% for i in breadcrumbs %}{% set url, _, title = i.strip().partition(' ') %}{{ title|e }} &raquo; {% endfor %}
 {% endif %}
-{% if page.title == SITENAME %}
+{% if page.title == SITENAME|e %}
 {{ page.title -}}
 {% else %}
-{{ page.title }} | {{ SITENAME -}}
+{{ page.title }} | {{ SITENAME|e -}}
 {% endif %}
 {% endblock %}
 
 {% block head %}
   {{- super() -}}
   {% if page.description %}
-  <meta name="description" content="{{ page.description }}" />
+  <meta name="description" content="{{ page.description|striptags|e }}" />
   {% endif %}
   <meta property="og:title" content="{{ page.title }}" />
   <meta name="twitter:title" content="{{ page.title }}" />
-  <meta property="og:url" content="{{ page.url|format_siteurl }}" />
-  <meta name="twitter:url" content="{{ page.url|format_siteurl }}" />
+  <meta property="og:url" content="{{ page.url|format_siteurl|e }}" />
+  <meta name="twitter:url" content="{{ page.url|format_siteurl|e }}" />
   {% if page.summary %}
-  <meta property="og:description" content="{{ page.summary|striptags }}" />
-  <meta name="twitter:description" content="{{ page.summary|striptags }}" />
+  <meta property="og:description" content="{{ page.summary|striptags|e }}" />
+  <meta name="twitter:description" content="{{ page.summary|striptags|e }}" />
   {% endif %}
   {% if page.cover %}
-  <meta property="og:image" content="{{ page.cover|expand_link(page) }}" />
+  <meta property="og:image" content="{{ page.cover|expand_link(page)|e }}" />
   <meta name="twitter:card" content="summary_large_image" />
-  <meta name="twitter:image" content="{{ page.cover|expand_link(page) }}" />
+  <meta name="twitter:image" content="{{ page.cover|expand_link(page)|e }}" />
   {% else %}
   <meta name="twitter:card" content="summary" />
   {% endif %}
@@ -41,7 +41,7 @@
   {% if page.css %}
   {% set styles = page.css.strip().split('\n') %}
   {% for style in styles %}
-  <link rel="stylesheet" href="{{ style|expand_link(page) }}" />
+  <link rel="stylesheet" href="{{ style|expand_link(page)|e }}" />
   {% endfor %}
   {% endif %}
 {% endblock %}
@@ -60,7 +60,7 @@
 {% endif %}
 <article>
   {% if page.landing %}
-  <div id="m-landing-image"{% if page.cover %} style="background-image: url('{{ page.cover|expand_link(page) }}');"{% endif %}>
+  <div id="m-landing-image"{% if page.cover %} style="background-image: url('{{ page.cover|expand_link(page)|e }}');"{% endif %}>
     <div id="m-landing-cover">
       <div class="m-container">
 <!-- landing -->
@@ -80,7 +80,7 @@
             {% set breadcrumbs = page.breadcrumb.strip().split('\n') %}
             {% for i in breadcrumbs %}
             {% set url, _, title = i.strip().partition(' ') %}
-            <a href="{{ url|expand_link(page) }}">{{ title }}</a> &raquo;
+            <a href="{{ url|expand_link(page)|e }}">{{ title|e }}</a> &raquo;
             {% endfor %}
           </span>
           {{ page.title }}
index da0ae46066786608e268b4c3c65ce38ece656c9c..42a8dc5c3218011bd2045e04922d1038c9cc8131 100644 (file)
@@ -1,7 +1,7 @@
 {% if DEFAULT_PAGINATION %}
 <div class="m-article-pagination">
-  {%- if articles_page.has_previous() %}<a href="{{ articles_previous_page.url|format_siteurl }}">&laquo; newer articles</a> | {% endif -%}
+  {%- if articles_page.has_previous() %}<a href="{{ articles_previous_page.url|format_siteurl|e }}">&laquo; newer articles</a> | {% endif -%}
   page {{ articles_page.number }}
-  {%- if articles_page.has_next() %} | <a href="{{ articles_next_page.url|format_siteurl }}">older articles &raquo;</a>{% endif -%}
+  {%- if articles_page.has_next() %} | <a href="{{ articles_next_page.url|format_siteurl|e }}">older articles &raquo;</a>{% endif -%}
 </div>
 {% endif %}
index b7cec94fa88285511f781c9a9aa0b00c8ae3a609..0f4e83b6362616f1a75c2be3c198ec68bcc59f35 100644 (file)
@@ -1,9 +1,9 @@
 {% extends "base_blog_section.html" %}
 
-{% block title %}Posts tagged {{ tag }} | {{ M_BLOG_NAME }}{% endblock %}
+{% block title %}Posts tagged {{ tag|e }} | {{ M_BLOG_NAME|e }}{% endblock %}
 
 {% block content_title %}
       <div class="m-info m-note">
-        Showing only posts tagged <em>{{ tag }}</em>. <a href="{{ M_BLOG_URL|format_siteurl }}">Show all posts.</a>
+        Showing only posts tagged <em>{{ tag|e }}</em>. <a href="{{ M_BLOG_URL|format_siteurl|e }}">Show all posts.</a>
       </div>
 {% endblock %}
diff --git a/pelican-theme/test/blog_html_escape/article-jumbo.html b/pelican-theme/test/blog_html_escape/article-jumbo.html
new file mode 100644 (file)
index 0000000..f773b09
--- /dev/null
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one | &lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <meta name="description" content="And &lt;&amp;&gt; in description." />
+  <meta name="keywords" content="And &lt;&amp;&gt; in tag" />
+  <meta property="og:title" content="Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one" />
+  <meta name="twitter:title" content="Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one" />
+  <meta property="og:url" content="article-jumbo.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="twitter:url" content="article-jumbo.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta property="og:description" content="And &lt;&amp;&gt; in summary." />
+  <meta name="twitter:description" content="And &lt;&amp;&gt; in summary." />
+  <meta property="og:image" content="image.jpg?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="twitter:card" content="summary_large_image" />
+  <meta name="twitter:image" content="image.jpg?and&amp;in&amp;url=&#34;&#34;" />
+  <meta property="og:type" content="article" />
+</head>
+<body>
+<header><nav id="navigation" class="m-navbar-jumbo">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+  <article id="m-jumbo">
+    <header>
+      <div id="m-jumbo-image" style="background-image: url('image.jpg?and&amp;in&amp;url=&#34;&#34;');">
+        <div id="m-jumbo-cover">
+          <div class="m-container">
+            <div class="m-row">
+              <div class="m-col-t-6 m-col-s-5 m-push-s-1 m-text-left">Dec 10, 2017</div>
+              <div class="m-col-t-6 m-col-s-5 m-push-s-1 m-text-right"><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></div>
+            </div>
+            <div class="m-row">
+              <div class="m-col-t-12 m-col-s-10 m-push-s-1 m-col-m-8 m-push-m-2">
+                <h1><a href="article-jumbo.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one">Article with &lt;&amp;&gt;</a></h1>
+                <h2>a &lt;&amp;&gt; jumbo one</h2>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="m-container">
+        <div class="m-row">
+          <div class="m-col-m-10 m-push-m-1 m-nopady">
+            <p>And &lt;&amp;&gt; in summary.</p>
+          </div>
+        </div>
+      </div>
+    </header>
+    <div class="m-container m-container-inflatable">
+      <div class="m-row">
+        <div class="m-col-m-10 m-push-m-1 m-nopady">
+<!-- content -->
+<p>And &lt;&amp;&gt; in content.</p>
+<!-- /content -->
+        </div>
+      </div>
+    </div>
+    <footer class="m-container">
+      <div class="m-row">
+        <div class="m-col-m-10 m-push-m-1 m-nopadb">
+          <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-10T00:00:00+00:00">Dec 10, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+        </div>
+      </div>
+    </footer>
+  </article>
+  <nav class="m-navpanel m-container">
+    <div class="m-row">
+      <div class="m-col-s-4 m-col-l-2 m-push-l-1">
+        <h3>Categories</h3>
+        <ol class="m-block-bar-s">
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ol>
+      </div>
+      <div class="m-col-s-4 m-col-l-2 m-push-l-3">
+        <h3>Authors</h3>
+        <ol class="m-block-bar-s">
+          <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+        </ol>
+      </div>
+      <div class="m-col-s-4 m-col-l-2 m-push-l-5">
+        <h3>Tag cloud</h3>
+        <ul class="m-tagcloud">
+          <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+        </ul>
+      </div>
+    </div>
+  </nav>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
diff --git a/pelican-theme/test/blog_html_escape/article-jumbo.rst b/pelican-theme/test/blog_html_escape/article-jumbo.rst
new file mode 100644 (file)
index 0000000..419af20
--- /dev/null
@@ -0,0 +1,12 @@
+Article with <&> — a <&> jumbo one
+##################################
+
+:date: 2017-12-10
+:cover: image.jpg?and&in&url=""
+:author: And <&> in author
+:description: And <&> in description.
+:tags: And <&> in tag
+:category: And <&> in category
+:summary: And <&> in summary.
+
+And <&> in content.
diff --git a/pelican-theme/test/blog_html_escape/article.html b/pelican-theme/test/blog_html_escape/article.html
new file mode 100644 (file)
index 0000000..5a3d57e
--- /dev/null
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Article with &lt;&amp;&gt; in title | &lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <meta name="description" content="And &lt;&amp;&gt; in description." />
+  <meta name="keywords" content="And &lt;&amp;&gt; in tag" />
+  <meta property="og:title" content="Article with &lt;&amp;&gt; in title" />
+  <meta name="twitter:title" content="Article with &lt;&amp;&gt; in title" />
+  <meta property="og:url" content="article.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="twitter:url" content="article.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta property="og:description" content="And &lt;&amp;&gt; in summary." />
+  <meta name="twitter:description" content="And &lt;&amp;&gt; in summary." />
+  <meta name="twitter:card" content="summary" />
+  <meta property="og:type" content="article" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <article class="m-col-m-10 m-nopadb">
+      <header>
+        <h1><a href="article.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; in title">
+          <time class="m-date" datetime="2017-12-09T00:00:00+00:00">
+            Dec <span class="m-date-day">09</span> 2017
+          </time>
+          Article with &lt;&amp;&gt; in title
+        </a></h1>
+        <p>And &lt;&amp;&gt; in summary.</p>
+      </header>
+      <div class="m-clearfix-l"></div>
+<!-- content -->
+<p>And &lt;&amp;&gt; in content.</p>
+<!-- /content -->
+      <footer>
+        <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-09T00:00:00+00:00">Dec 09, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+      </footer>
+    </article>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+      </ol>
+      <h3>Authors</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+      </ol>
+      <h3>Tag cloud</h3>
+      <ul class="m-tagcloud">
+        <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+      </ul>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
diff --git a/pelican-theme/test/blog_html_escape/article.rst b/pelican-theme/test/blog_html_escape/article.rst
new file mode 100644 (file)
index 0000000..1d474b5
--- /dev/null
@@ -0,0 +1,11 @@
+Article with <&> in title
+#########################
+
+:date: 2017-12-09
+:author: And <&> in author
+:description: And <&> in description.
+:tags: And <&> in tag
+:category: And <&> in category
+:summary: And <&> in summary.
+
+And <&> in content.
diff --git a/pelican-theme/test/blog_html_escape/author-and-in-author.html b/pelican-theme/test/blog_html_escape/author-and-in-author.html
new file mode 100644 (file)
index 0000000..a6e2ef3
--- /dev/null
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Posts by And &lt;&amp;&gt; in author | &lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <link rel="next" href="index2.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <div class="m-col-m-10">
+      <div class="m-info m-note">
+        Showing only posts by <em>And &lt;&amp;&gt; in author</em>. <a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Show all posts.</a>
+      </div>
+      <article>
+        <header>
+          <h1><a href="article-jumbo.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one">
+            <time class="m-date" datetime="2017-12-10T00:00:00+00:00">
+              Dec <span class="m-date-day">10</span> 2017
+            </time>
+            Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one
+          </a></h1>
+          <p>And &lt;&amp;&gt; in summary.</p>
+        </header>
+        <footer>
+          <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-10T00:00:00+00:00">Dec 10, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+        </footer>
+        <div class="m-clearfix-l"></div>
+      </article>
+      <div class="m-article-pagination">page 1 | <a href="index2.html?and&amp;in&amp;url=&#34;&#34;">older articles &raquo;</a></div>
+    </div>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+      </ol>
+      <h3>Authors</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+      </ol>
+      <h3>Tag cloud</h3>
+      <ul class="m-tagcloud">
+        <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+      </ul>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
diff --git a/pelican-theme/test/blog_html_escape/author-and-in-author2.html b/pelican-theme/test/blog_html_escape/author-and-in-author2.html
new file mode 100644 (file)
index 0000000..abd1f69
--- /dev/null
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Posts by And &lt;&amp;&gt; in author | &lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <link rel="prev" href="index.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <div class="m-col-m-10">
+      <div class="m-info m-note">
+        Showing only posts by <em>And &lt;&amp;&gt; in author</em>. <a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Show all posts.</a>
+      </div>
+      <article>
+        <header>
+          <h1><a href="article.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; in title">
+            <time class="m-date" datetime="2017-12-09T00:00:00+00:00">
+              Dec <span class="m-date-day">09</span> 2017
+            </time>
+            Article with &lt;&amp;&gt; in title
+          </a></h1>
+          <p>And &lt;&amp;&gt; in summary.</p>
+        </header>
+        <footer>
+          <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-09T00:00:00+00:00">Dec 09, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+        </footer>
+        <div class="m-clearfix-l"></div>
+      </article>
+      <div class="m-article-pagination"><a href="index.html?and&amp;in&amp;url=&#34;&#34;">&laquo; newer articles</a> | page 2</div>
+    </div>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+      </ol>
+      <h3>Authors</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+      </ol>
+      <h3>Tag cloud</h3>
+      <ul class="m-tagcloud">
+        <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+      </ul>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
diff --git a/pelican-theme/test/blog_html_escape/category-and-in-category.html b/pelican-theme/test/blog_html_escape/category-and-in-category.html
new file mode 100644 (file)
index 0000000..3d2e32b
--- /dev/null
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>And &lt;&amp;&gt; in category | &lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <link rel="next" href="index2.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <div class="m-col-m-10">
+      <div class="m-info m-note">
+        Showing only posts in <em>And &lt;&amp;&gt; in category</em>. <a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Show all posts.</a>
+      </div>
+      <article>
+        <header>
+          <h1><a href="article-jumbo.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one">
+            <time class="m-date" datetime="2017-12-10T00:00:00+00:00">
+              Dec <span class="m-date-day">10</span> 2017
+            </time>
+            Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one
+          </a></h1>
+          <p>And &lt;&amp;&gt; in summary.</p>
+        </header>
+        <footer>
+          <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-10T00:00:00+00:00">Dec 10, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+        </footer>
+        <div class="m-clearfix-l"></div>
+      </article>
+      <div class="m-article-pagination">page 1 | <a href="index2.html?and&amp;in&amp;url=&#34;&#34;">older articles &raquo;</a></div>
+    </div>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+      </ol>
+      <h3>Authors</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+      </ol>
+      <h3>Tag cloud</h3>
+      <ul class="m-tagcloud">
+        <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+      </ul>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/pelican-theme/test/blog_html_escape/category-and-in-category2.html b/pelican-theme/test/blog_html_escape/category-and-in-category2.html
new file mode 100644 (file)
index 0000000..96ded62
--- /dev/null
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>And &lt;&amp;&gt; in category | &lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <link rel="prev" href="index.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <div class="m-col-m-10">
+      <div class="m-info m-note">
+        Showing only posts in <em>And &lt;&amp;&gt; in category</em>. <a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Show all posts.</a>
+      </div>
+      <article>
+        <header>
+          <h1><a href="article.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; in title">
+            <time class="m-date" datetime="2017-12-09T00:00:00+00:00">
+              Dec <span class="m-date-day">09</span> 2017
+            </time>
+            Article with &lt;&amp;&gt; in title
+          </a></h1>
+          <p>And &lt;&amp;&gt; in summary.</p>
+        </header>
+        <footer>
+          <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-09T00:00:00+00:00">Dec 09, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+        </footer>
+        <div class="m-clearfix-l"></div>
+      </article>
+      <div class="m-article-pagination"><a href="index.html?and&amp;in&amp;url=&#34;&#34;">&laquo; newer articles</a> | page 2</div>
+    </div>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+      </ol>
+      <h3>Authors</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+      </ol>
+      <h3>Tag cloud</h3>
+      <ul class="m-tagcloud">
+        <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+      </ul>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/pelican-theme/test/blog_html_escape/index.html b/pelican-theme/test/blog_html_escape/index.html
new file mode 100644 (file)
index 0000000..6565563
--- /dev/null
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>&lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <link rel="next" href="index2.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <div class="m-col-m-10">
+      <article>
+        <header>
+          <h1><a href="article-jumbo.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one">
+            <time class="m-date" datetime="2017-12-10T00:00:00+00:00">
+              Dec <span class="m-date-day">10</span> 2017
+            </time>
+            Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one
+          </a></h1>
+          <p>And &lt;&amp;&gt; in summary.</p>
+        </header>
+        <div class="m-clearfix-l"></div>
+<!-- content -->
+<p>And &lt;&amp;&gt; in content.</p>
+<!-- /content -->
+        <footer>
+          <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-10T00:00:00+00:00">Dec 10, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+        </footer>
+      </article>
+      <div class="m-article-pagination">page 1 | <a href="index2.html?and&amp;in&amp;url=&#34;&#34;">older articles &raquo;</a></div>
+    </div>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+      </ol>
+      <h3>Authors</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+      </ol>
+      <h3>Tag cloud</h3>
+      <ul class="m-tagcloud">
+        <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+      </ul>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
diff --git a/pelican-theme/test/blog_html_escape/index2.html b/pelican-theme/test/blog_html_escape/index2.html
new file mode 100644 (file)
index 0000000..05f65bb
--- /dev/null
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>&lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <link rel="prev" href="index.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <div class="m-col-m-10">
+      <article>
+        <header>
+          <h1><a href="article.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; in title">
+            <time class="m-date" datetime="2017-12-09T00:00:00+00:00">
+              Dec <span class="m-date-day">09</span> 2017
+            </time>
+            Article with &lt;&amp;&gt; in title
+          </a></h1>
+          <p>And &lt;&amp;&gt; in summary.</p>
+        </header>
+        <footer>
+          <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-09T00:00:00+00:00">Dec 09, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+        </footer>
+        <div class="m-clearfix-l"></div>
+      </article>
+      <div class="m-article-pagination"><a href="index.html?and&amp;in&amp;url=&#34;&#34;">&laquo; newer articles</a> | page 2</div>
+    </div>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+      </ol>
+      <h3>Authors</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+      </ol>
+      <h3>Tag cloud</h3>
+      <ul class="m-tagcloud">
+        <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+      </ul>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/pelican-theme/test/blog_html_escape/tag-and-in-tag.html b/pelican-theme/test/blog_html_escape/tag-and-in-tag.html
new file mode 100644 (file)
index 0000000..feac1b7
--- /dev/null
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Posts tagged And &lt;&amp;&gt; in tag | &lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <link rel="next" href="index2.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <div class="m-col-m-10">
+      <div class="m-info m-note">
+        Showing only posts tagged <em>And &lt;&amp;&gt; in tag</em>. <a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Show all posts.</a>
+      </div>
+      <article>
+        <header>
+          <h1><a href="article-jumbo.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one">
+            <time class="m-date" datetime="2017-12-10T00:00:00+00:00">
+              Dec <span class="m-date-day">10</span> 2017
+            </time>
+            Article with &lt;&amp;&gt; — a &lt;&amp;&gt; jumbo one
+          </a></h1>
+          <p>And &lt;&amp;&gt; in summary.</p>
+        </header>
+        <footer>
+          <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-10T00:00:00+00:00">Dec 10, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+        </footer>
+        <div class="m-clearfix-l"></div>
+      </article>
+      <div class="m-article-pagination">page 1 | <a href="index2.html?and&amp;in&amp;url=&#34;&#34;">older articles &raquo;</a></div>
+    </div>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+      </ol>
+      <h3>Authors</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+      </ol>
+      <h3>Tag cloud</h3>
+      <ul class="m-tagcloud">
+        <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+      </ul>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/pelican-theme/test/blog_html_escape/tag-and-in-tag2.html b/pelican-theme/test/blog_html_escape/tag-and-in-tag2.html
new file mode 100644 (file)
index 0000000..930150f
--- /dev/null
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Posts tagged And &lt;&amp;&gt; in tag | &lt;&amp;&gt; in blog name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <link rel="prev" href="index.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">A Pelican Blog</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <div class="m-col-m-10">
+      <div class="m-info m-note">
+        Showing only posts tagged <em>And &lt;&amp;&gt; in tag</em>. <a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Show all posts.</a>
+      </div>
+      <article>
+        <header>
+          <h1><a href="article.html?and&amp;in&amp;url=&#34;&#34;" rel="bookmark" title="Permalink to Article with &lt;&amp;&gt; in title">
+            <time class="m-date" datetime="2017-12-09T00:00:00+00:00">
+              Dec <span class="m-date-day">09</span> 2017
+            </time>
+            Article with &lt;&amp;&gt; in title
+          </a></h1>
+          <p>And &lt;&amp;&gt; in summary.</p>
+        </header>
+        <footer>
+          <p>Posted by <a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a> on <time datetime="2017-12-09T00:00:00+00:00">Dec 09, 2017</time> in <a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a>. Tags: <a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a>.</p>
+        </footer>
+        <div class="m-clearfix-l"></div>
+      </article>
+      <div class="m-article-pagination"><a href="index.html?and&amp;in&amp;url=&#34;&#34;">&laquo; newer articles</a> | page 2</div>
+    </div>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+      </ol>
+      <h3>Authors</h3>
+      <ol class="m-block-bar-m">
+        <li><a href="author-and-in-author.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in author</a></li>
+      </ol>
+      <h3>Tag cloud</h3>
+      <ul class="m-tagcloud">
+        <li class="m-tag-5"><a href="tag-and-in-tag.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in tag</a></li>
+      </ul>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="./">An &lt;&amp;&gt; in link</a></h3>
+        <ul>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="archives.html?and&amp;in&amp;url=&#34;&#34;">Blog</a></h3>
+        <ul>
+          <li><a href="category-and-in-category.html?and&amp;in&amp;url=&#34;&#34;">And &lt;&amp;&gt; in category</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/pelican-theme/test/layout_html_escape/index.html b/pelican-theme/test/layout_html_escape/index.html
new file mode 100644 (file)
index 0000000..a05803f
--- /dev/null
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>A &lt;&amp;&gt; blog</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m"><img src="image.png?and&amp;in&amp;url=&#34;&#34;" />&lt;&amp;&gt;</a>
+      <a id="m-navbar-show" href="#navigation" title="Show navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+      <a id="m-navbar-hide" href="#" title="Hide navigation" class="m-col-t-3 m-hide-m m-text-right"></a>
+      <div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
+        <div class="m-row">
+          <ol class="m-col-t-6 m-col-m-none">
+            <li>
+              <a href="item.html?and&amp;in&amp;url=&#34;&#34;">An &lt;&amp;&gt; item</a>
+              <ol>
+                <li><a href="sub.html?and&amp;in&amp;url=&#34;&#34;">A &lt;&amp;&gt; subitem</a></li>
+              </ol>
+            </li>
+            <li><a href="item.html?and&amp;in&amp;url=&#34;&#34;">Another &lt;&amp;&gt; item</a></li>
+          </ol>
+          <ol class="m-col-t-6 m-col-m-none" start="3">
+            <li>
+              <a href="item.html?and&amp;in&amp;url=&#34;&#34;">An &lt;&amp;&gt; item</a>
+              <ol>
+                <li><a href="sub.html?and&amp;in&amp;url=&#34;&#34;">A &lt;&amp;&gt; subitem</a></li>
+              </ol>
+            </li>
+            <li><a href="item.html?and&amp;in&amp;url=&#34;&#34;">Another &lt;&amp;&gt; item</a></li>
+          </ol>
+        </div>
+      </div>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container">
+  <div class="m-row">
+    <div class="m-col-m-10">
+      <div class="m-note m-success">
+        <h3>Congratulations!</h3>
+        The m.css theme is alive and kicking! Now, feed it some articles so it doesn't feel so empty :)
+      </div>
+    </div>
+    <nav class="m-navpanel m-col-m-2">
+      <h3>Categories</h3>
+      <ol class="m-block-bar-m">
+        <li><em class="m-text m-dim">(none yet)</em></li>
+      </ol>
+    </nav>
+  </div>
+</div>
+</main>
+<footer><nav>
+  <div class="m-container">
+    <div class="m-row">
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="item.html?and&amp;in&amp;url=&#34;&#34;">An &lt;&amp;&gt; item</a></h3>
+        <ul>
+          <li><a href="sub.html?and&amp;in&amp;url=&#34;&#34;">A &lt;&amp;&gt; subitem</a></li>
+        </ul>
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="item.html?and&amp;in&amp;url=&#34;&#34;">An &lt;&amp;&gt; item</a></h3>
+        <ul>
+          <li><a href="sub.html?and&amp;in&amp;url=&#34;&#34;">A &lt;&amp;&gt; subitem</a></li>
+        </ul>
+      </div>
+      <div class="m-clearfix-t"></div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="item.html?and&amp;in&amp;url=&#34;&#34;">An &lt;&amp;&gt; item</a></h3>
+        <ul>
+          <li><a href="sub.html?and&amp;in&amp;url=&#34;&#34;">A &lt;&amp;&gt; subitem</a></li>
+        </ul>
+      </div>
+      <div class="m-col-s-3 m-col-t-6">
+        <h3><a href="item.html?and&amp;in&amp;url=&#34;&#34;">An &lt;&amp;&gt; item</a></h3>
+        <ul>
+          <li><a href="sub.html?and&amp;in&amp;url=&#34;&#34;">A &lt;&amp;&gt; subitem</a></li>
+        </ul>
+      </div>
+    </div>
+    <div class="m-row">
+      <div class="m-col-l-10 m-push-l-1">
+        <p>An &lt;&amp;&gt; in fine print.</p>
+      </div>
+    </div>
+  </div>
+</nav></footer>
+</body>
+</html>
diff --git a/pelican-theme/test/page_html_escape/breadcrumb.html b/pelican-theme/test/page_html_escape/breadcrumb.html
new file mode 100644 (file)
index 0000000..5334213
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>And &lt;&amp;&gt; in breadcrumb &raquo; Page with &lt;&amp;&gt; in title | &lt;&amp;&gt; in site name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <meta property="og:title" content="Page with &lt;&amp;&gt; in title" />
+  <meta name="twitter:title" content="Page with &lt;&amp;&gt; in title" />
+  <meta property="og:url" content="breadcrumb.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="twitter:url" content="breadcrumb.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="twitter:card" content="summary" />
+  <meta property="og:type" content="website" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">&lt;&amp;&gt; in site name</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<article>
+  <div class="m-container m-container-inflatable">
+    <div class="m-row">
+      <div class="m-col-l-10 m-push-l-1">
+        <h1>
+          <span class="m-breadcrumb">
+            <a href="index.html?and&amp;in&amp;breadcrumb=&#34;&#34;">And &lt;&amp;&gt; in breadcrumb</a> &raquo;
+          </span>
+          Page with &lt;&amp;&gt; in title
+        </h1>
+      </div>
+    </div>
+  </div>
+</article>
+</main>
+</body>
+</html>
diff --git a/pelican-theme/test/page_html_escape/breadcrumb.rst b/pelican-theme/test/page_html_escape/breadcrumb.rst
new file mode 100644 (file)
index 0000000..0a3dcec
--- /dev/null
@@ -0,0 +1,4 @@
+Page with <&> in title
+######################
+
+:breadcrumb: index.html?and&in&breadcrumb="" And <&> in breadcrumb
diff --git a/pelican-theme/test/page_html_escape/content.html b/pelican-theme/test/page_html_escape/content.html
new file mode 100644 (file)
index 0000000..bd66d3b
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Escaping in content | &lt;&amp;&gt; in site name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <meta property="og:title" content="Escaping in content" />
+  <meta name="twitter:title" content="Escaping in content" />
+  <meta property="og:url" content="content.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="twitter:url" content="content.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta property="og:description" content="Self link (overriden URL) Self link with more params added Link to other page (it doesn&#39;t have URL overriden) Link outside." />
+  <meta name="twitter:description" content="Self link (overriden URL) Self link with more params added Link to other page (it doesn&#39;t have URL overriden) Link outside." />
+  <meta name="twitter:card" content="summary" />
+  <meta property="og:type" content="website" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">&lt;&amp;&gt; in site name</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<article>
+  <div class="m-container m-container-inflatable">
+    <div class="m-row">
+      <div class="m-col-l-10 m-push-l-1">
+        <h1>Escaping in content</h1>
+<!-- content -->
+<ul>
+<li><a href="./page.html?and&amp;overriden&amp;url=&quot;&quot;">Self link</a> (overriden URL)</li>
+<li><a href="./page.html?and&amp;overriden&amp;url=&quot;&quot;#so=this&amp;works=&quot;bad&quot;">Self link with more params added</a></li>
+<li><a href="./landing.html?and&amp;in&amp;url=&quot;&quot;">Link to other page</a> (it doesn't have URL overriden)</li>
+<li><a href="http://a.site/?and&amp;in&amp;url=&quot;&quot;">Link outside</a>.</li>
+</ul>
+<!-- /content -->
+      </div>
+    </div>
+  </div>
+</article>
+</main>
+</body>
+</html>
diff --git a/pelican-theme/test/page_html_escape/content.rst b/pelican-theme/test/page_html_escape/content.rst
new file mode 100644 (file)
index 0000000..2bdfeb8
--- /dev/null
@@ -0,0 +1,7 @@
+Escaping in content
+###################
+
+-   `Self link <{filename}/page.rst>`_ (overriden URL)
+-   `Self link with more params added <{filename}/page.rst#so=this&works="bad">`_
+-   `Link to other page <{filename}/landing.rst>`_ (it doesn't have URL overriden)
+-   `Link outside <http://a.site/?and&in&url="">`_.
diff --git a/pelican-theme/test/page_html_escape/landing.html b/pelican-theme/test/page_html_escape/landing.html
new file mode 100644 (file)
index 0000000..3e8bd33
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>&lt;&amp;&gt; in site name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <meta property="og:title" content="&lt;&amp;&gt; in site name" />
+  <meta name="twitter:title" content="&lt;&amp;&gt; in site name" />
+  <meta property="og:url" content="landing.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="twitter:url" content="landing.html?and&amp;in&amp;url=&#34;&#34;" />
+  <meta property="og:description" content="Page text." />
+  <meta name="twitter:description" content="Page text." />
+  <meta property="og:image" content="image.jpg?and&amp;in&amp;url=&#34;&#34;" />
+  <meta name="twitter:card" content="summary_large_image" />
+  <meta name="twitter:image" content="image.jpg?and&amp;in&amp;url=&#34;&#34;" />
+  <meta property="og:type" content="website" />
+</head>
+<body>
+<header><nav id="navigation" class="m-navbar-landing">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">&lt;&amp;&gt; in site name</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<article>
+  <div id="m-landing-image" style="background-image: url('image.jpg?and&amp;in&amp;url=&#34;&#34;');">
+    <div id="m-landing-cover">
+      <div class="m-container">
+<!-- landing -->
+<div class="m-row">
+<div class="m-col-m-6 m-push-m-3">
+Landing text.</div>
+</div>
+<!-- /landing -->
+      </div>
+    </div>
+  </div>
+  <div class="m-container m-container-inflatable">
+    <div class="m-row">
+      <div class="m-col-l-10 m-push-l-1">
+<!-- content -->
+<p>Page text.</p>
+<!-- /content -->
+      </div>
+    </div>
+  </div>
+</article>
+</main>
+</body>
+</html>
diff --git a/pelican-theme/test/page_html_escape/landing.rst b/pelican-theme/test/page_html_escape/landing.rst
new file mode 100644 (file)
index 0000000..b0c836c
--- /dev/null
@@ -0,0 +1,12 @@
+<&> in site name
+################
+
+:cover: image.jpg?and&in&url=""
+:landing:
+    .. container:: m-row
+
+        .. container:: m-col-m-6 m-push-m-3
+
+            Landing text.
+
+Page text.
diff --git a/pelican-theme/test/page_html_escape/page.html b/pelican-theme/test/page_html_escape/page.html
new file mode 100644 (file)
index 0000000..46eaadd
--- /dev/null
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Page with &lt;&amp;&gt; in title | &lt;&amp;&gt; in site name</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,400i,600%7CSource+Sans+Pro:400,400i,600,600i" />
+  <link rel="stylesheet" href="static/m-dark.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <meta name="description" content="And &lt;&amp;&gt; in description." />
+  <meta property="og:title" content="Page with &lt;&amp;&gt; in title" />
+  <meta name="twitter:title" content="Page with &lt;&amp;&gt; in title" />
+  <meta property="og:url" content="page.html?and&amp;overriden&amp;url=&#34;&#34;" />
+  <meta name="twitter:url" content="page.html?and&amp;overriden&amp;url=&#34;&#34;" />
+  <meta property="og:description" content="And &lt;&amp;&gt; in summary." />
+  <meta name="twitter:description" content="And &lt;&amp;&gt; in summary." />
+  <meta name="twitter:card" content="summary" />
+  <meta property="og:type" content="website" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="./" id="m-navbar-brand" class="m-col-t-9 m-col-m-none m-left-m">&lt;&amp;&gt; in site name</a>
+    </div>
+  </div>
+</nav></header>
+<main>
+<div class="m-container m-container-inflatable">
+  <div class="m-row">
+    <div class="m-col-l-10 m-push-l-1 m-nopadb">
+<!-- header -->
+<p>And &lt;&amp;&gt; in header.</p>
+<!-- /header -->
+    </div>
+  </div>
+</div>
+<article>
+  <div class="m-container m-container-inflatable">
+    <div class="m-row">
+      <div class="m-col-l-10 m-push-l-1">
+        <h1>Page with &lt;&amp;&gt; in title</h1>
+<!-- content -->
+<p>And &lt;&amp;&gt; in content.</p>
+<!-- /content -->
+      </div>
+    </div>
+  </div>
+</article>
+<div class="m-container m-container-inflatable">
+  <div class="m-row">
+    <div class="m-col-l-10 m-push-l-1 m-nopadt">
+<!-- footer -->
+<p>And &lt;&amp;&gt; in footer.</p>
+<!-- /footer -->
+    </div>
+  </div>
+</div>
+</main>
+</body>
+</html>
diff --git a/pelican-theme/test/page_html_escape/page.rst b/pelican-theme/test/page_html_escape/page.rst
new file mode 100644 (file)
index 0000000..fd558dd
--- /dev/null
@@ -0,0 +1,10 @@
+Page with <&> in title
+######################
+
+:url: page.html?and&overriden&url=""
+:description: And <&> in description.
+:summary: And <&> in summary.
+:header: And <&> in header.
+:footer: And <&> in footer.
+
+And <&> in content.
index e530b40b64bb4e854542a37162a744e8e7c28a29..df49568425714253c3643ca89fc4e718c4e24757 100644 (file)
@@ -396,3 +396,34 @@ class CollapseFirstBothHideSummaryBoth(BlogTestCase):
         # Both classic and jumbo article should have summary shown
         self.assertEqual(*self.actual_expected_contents('article.html'))
         self.assertEqual(*self.actual_expected_contents('article-jumbo.html'))
+
+class HtmlEscape(BlogTestCase):
+    def __init__(self, *args, **kwargs):
+        super().__init__(__file__, 'html_escape', *args, **kwargs)
+
+    def test(self):
+        self.run_pelican({
+            'M_BLOG_NAME': '<&> in blog name',
+            'M_BLOG_URL': 'archives.html?and&in&url=""',
+            'ARTICLE_URL': '{slug}.html?and&in&url=""',
+            'AUTHOR_URL': 'author-{slug}.html?and&in&url=""',
+            'CATEGORY_URL': 'category-{slug}.html?and&in&url=""',
+            'TAG_URL': 'tag-{slug}.html?and&in&url=""',
+            'M_LINKS_FOOTER2': [('An <&> in link', '#')],
+            'M_SHOW_AUTHOR_LIST': True,
+            'DEFAULT_PAGINATION': 1,
+            'PAGINATION_PATTERNS':
+                [(1, 'index.html?and&in&url=""', '{name}.html'),
+                 (2, 'index{number}.html?and&in&url=""', '{name}{number}.html')],
+            'DIRECT_TEMPLATES': ['index', 'archives'],
+            'PAGINATED_DIRECT_TEMPLATES': ['index', 'archives'],
+            'FORMATTED_FIELDS': ['summary', 'description']
+        })
+
+        # Verify that everything is properly escaped everywhere
+        self.assertEqual(*self.actual_expected_contents('index.html'))
+        self.assertEqual(*self.actual_expected_contents('index2.html'))
+        self.assertEqual(*self.actual_expected_contents('archives.html', 'index.html'))
+        self.assertEqual(*self.actual_expected_contents('archives2.html', 'index2.html'))
+        self.assertEqual(*self.actual_expected_contents('article.html'))
+        self.assertEqual(*self.actual_expected_contents('article-jumbo.html'))
index 333a25644984dda41deebc26f51cf6027698efcc..9cd181585f1b6f35e50962572dc56cd5f16f8d2c 100644 (file)
@@ -151,3 +151,42 @@ class DisableBlogLinks(BaseTestCase):
 
         # There should be just the first column
         self.assertEqual(*self.actual_expected_contents('index.html'))
+
+class HtmlEscape(BaseTestCase):
+    def __init__(self, *args, **kwargs):
+        super().__init__(__file__, 'html_escape', *args, **kwargs)
+
+    def test(self):
+        self.run_pelican({
+            'SITENAME': 'A <&> site',
+            'M_BLOG_NAME': 'A <&> blog',
+            'M_BLOG_URL': 'archives.html?and&in&url=""',
+            'M_SITE_LOGO': 'image.png?and&in&url=""',
+            'M_SITE_LOGO_TEXT': '<&>',
+            'M_LINKS_NAVBAR1': [
+                ('An <&> item', 'item.html?and&in&url=""', '', [
+                    ('A <&> subitem', 'sub.html?and&in&url=""', '')]),
+                ('Another <&> item', 'item.html?and&in&url=""', '', [])],
+            'M_LINKS_NAVBAR2': [
+                ('An <&> item', 'item.html?and&in&url=""', '', [
+                    ('A <&> subitem', 'sub.html?and&in&url=""', '')]),
+                ('Another <&> item', 'item.html?and&in&url=""', '', [])],
+            'M_LINKS_FOOTER1': [
+                ('An <&> item', 'item.html?and&in&url=""'),
+                ('A <&> subitem', 'sub.html?and&in&url=""')],
+            'M_LINKS_FOOTER2': [
+                ('An <&> item', 'item.html?and&in&url=""'),
+                ('A <&> subitem', 'sub.html?and&in&url=""')],
+            'M_LINKS_FOOTER3': [
+                ('An <&> item', 'item.html?and&in&url=""'),
+                ('A <&> subitem', 'sub.html?and&in&url=""')],
+            'M_LINKS_FOOTER4': [
+                ('An <&> item', 'item.html?and&in&url=""'),
+                ('A <&> subitem', 'sub.html?and&in&url=""')],
+            'M_FINE_PRINT': 'An <&> in fine print.',
+            'CATEGORY_URL': 'tag-{slug}.html?and&in&url=""'
+        })
+
+        # Verify that everything is properly escaped everywhere
+        self.assertEqual(*self.actual_expected_contents('index.html'))
+        self.assertEqual(*self.actual_expected_contents('archives.html', 'index.html'))
index 070a49d6281cedbaca9b7acca49515dc3b28a3bb..34ba4cb0b8243d85412add3aa293db7c36949128 100644 (file)
@@ -1,3 +1,9 @@
+import unittest
+
+import pelican
+
+from distutils.version import LooseVersion
+
 from test import PageTestCase
 
 class Page(PageTestCase):
@@ -83,3 +89,36 @@ class TitleSitenameAlias(PageTestCase):
 
         # The page title should be just one name, not both
         self.assertEqual(*self.actual_expected_contents('page.html'))
+
+class HtmlEscape(PageTestCase):
+    def __init__(self, *args, **kwargs):
+        super().__init__(__file__, 'html_escape', *args, **kwargs)
+
+    def test(self):
+        self.run_pelican({
+            'SITENAME': "<&> in site name",
+            'FORMATTED_FIELDS': ['summary', 'description', 'landing', 'header', 'footer'],
+            'PAGE_URL': '{slug}.html?and&in&url=""',
+        })
+
+        # Verify that everything is properly escaped everywhere. The landing
+        # page has the name same as site name and the title should contain just
+        # one.
+        self.assertEqual(*self.actual_expected_contents('page.html'))
+        self.assertEqual(*self.actual_expected_contents('landing.html'))
+        self.assertEqual(*self.actual_expected_contents('breadcrumb.html'))
+
+    # This is broken in Pelican until https://github.com/getpelican/pelican/issues/2260
+    # so we test in a separate xfail test case
+    @unittest.skipUnless(LooseVersion(pelican.__version__) > LooseVersion("3.7.1"),
+                         "Pelican doesn't produce expected results in this version")
+    def test_content(self):
+        self.run_pelican({
+            'SITENAME': "<&> in site name",
+            'FORMATTED_FIELDS': ['summary', 'description', 'landing', 'header', 'footer'],
+            'PAGE_URL': '{slug}.html?and&in&url=""',
+        })
+
+        # Verify that also the Pelican-produced content has correctly escaped
+        # everything.
+        self.assertEqual(*self.actual_expected_contents('content.html'))