.. role:: rst(code)
:language: rst
+.. |x| unicode:: U+2715 .. nicer multiply sign
The second largest offering of m.css is a full-featured theme for the
`Pelican static site generator <https://getpelican.com/>`_. The theme is
reserved.
"""
+`(Social) meta tags`_
+---------------------
+
+The :rst:`M_BLOG_DESCRIPTION` setting, if available, is used to populate
+:html:`<meta name="description">` on the index / archive page, which can be
+then shown in search engine results. For sharing pages on Twitter, Facebook and
+elsewhere, it's possible to configure site-wide `Open Graph <http://ogp.me/>`_
+and `Twitter Card <https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary-card-with-large-image>`_
+:html:`<meta>` tags:
+
+- ``og:site_name`` is set to :py:`M_SOCIAL_SITE_NAME`, if available
+- ``twitter:site`` / ``twitter:site:id`` is set to :py:`M_SOCIAL_TWITTER_SITE`
+ / :py:`M_SOCIAL_TWITTER_SITE_ID``, if available
+- Global ``og:title`` / ``twitter:title`` is set to :py:`M_BLOG_NAME` on
+ index and archive pages and to category/author/tag name on particular
+ filtering pages. This is overriden by particular pages and articles.
+- Global ``og:url`` is set to :py:`M_BLOG_URL` on index and archive pages and
+ to category/author/tag URL on particular filtering pages. Pagination is
+ *not* included in the URL. This is overriden by particular pages and
+ articles.
+- Global ``og:image`` / ``twitter:image`` is set to the
+ :py:`M_SOCIAL_IMAGE` setting, if available. The image is expected to be
+ smaller and square; Pelican internal linking capabilities are *not*
+ supported in this setting. This can be overriden by particular pages and
+ articles.
+- Global ``twitter:card`` is set to ``summary``. This is further affected by
+ metadata of particular pages and articles.
+- Global ``og:description`` / ``twitter:description`` is set to
+ :py:`M_SOCIAL_BLOG_SUMMARY` on index and archive pages.
+- Global ``og:type`` is set to ``website``. This is overriden by particular
+ pages and articles.
+
+See `(Social) meta tags for pages`_ and `(Social) meta tags for articles`_
+sections below for page- and article-specific :html:`<meta>` tags.
+
+.. note-danger::
+
+ The :html:`<meta name="keywords">` tag is not supported, as it doesn't
+ have any effect on search engine results at all.
+
+Example configuration to give sane defaults to all social meta tags:
+
+.. code:: py
+
+ M_BLOG_NAME = "Your Brand Blog"
+ M_BLOG_URL = 'http://blog.your.brand/'
+ M_BLOG_DESCRIPTION = "Your Brand is the brand that provides all that\'s needed."
+
+ M_SOCIAL_TWITTER_SITE = '@your.brand'
+ M_SOCIAL_TWITTER_SITE_ID = 1234567890
+ M_SOCIAL_IMAGE = 'http://your.brand/static/site.png'
+ M_SOCIAL_BLOG_SUMMARY = "This is the brand you need"
+
+.. block-success:: Recommended sizes for global site image
+
+ The theme assumes that the global site image is smaller and square in order
+ to appear just as a small thumbnail next to a link, not as large cover
+ image above it --- the reasoning beind is that there's no point in annoying
+ the users by decorating the global site links with the exact same large
+ image.
+
+ For Twitter, this is controlled explicitly by setting ``twitter:card``
+ to ``summary`` instead of ``summary_large_image``, but in case of Facebook,
+ it's needed to rely on their autodetection.
+ `Their documentation <https://developers.facebook.com/docs/sharing/best-practices/#images>`_
+ says that images smaller than 600\ |x|\ 315 px are displayed as small
+ thumbnails. Square image of size 256\ |x|\ 256 px is known to work well.
+
+ Note that the assumptions are different for pages and articles with
+ explicit cover images, see `(Social) meta tags for pages`_ below for
+ details.
+
+.. note-info::
+
+ You can see how links for default pages will display by pasting
+ URL of the `article listing page <{category}examples>`_ into either
+ `Facebook Debugger <https://developers.facebook.com/tools/debug/>`_ or
+ `Twitter Card Validator <https://cards-dev.twitter.com/validator>`_.
+
`Pages`_
========
`(Social) meta tags for pages`_
-------------------------------
-You can use :rst:`:description:` field to populate :html:`<meta name="description">`,
-which can be then shown in search engine results. Other than that, the field
-does not appear anywhere on the rendered page. It's recommended to add it to
-:py:`FORMATTED_FIELDS` so you can make use of the
+Every page has :html:`<link rel="canonical">` pointing to its URL to avoid
+duplicates in search engines when using GET parameters. In addition to the
+global meta tags described in `(Social) meta tags`_ above, you can use the
+:rst:`:description:` field to populate :html:`<meta name="description">`. Other
+than that, the field does not appear anywhere on the rendered page. If such
+field is not set, the description :html:`<meta>` tag is not rendered at all.
+It's recommended to add it to :py:`FORMATTED_FIELDS` so you can make use of the
`advanced typography features <{filename}/plugins/htmlsanity.rst#typography>`_
like smart quotes etc. in it:
FORMATTED_FIELDS += ['description']
-For sharing pages on Twitter, Facebook and elsewhere, both `Open Graph <http://ogp.me/>`_
-and `Twitter Card <https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary-card-with-large-image>`_
-:html:`<meta>` tags are supported:
+The global `Open Graph`_ and `Twitter Card`_ :html:`<meta>` tags are
+specialized for pages like this:
- Page title is mapped to ``og:title`` / ``twitter:title``
- Page URL is mapped to ``og:url``
that may not be what you want. This is also different from the
:rst:`:description:` field mentioned above and, unlike with articles,
:rst:`:summary:` doesn't appear anywhere on the rendered page.
-- The :rst:`:cover:` field (e.g. the one used on `landing pages <#landing-pages>`_),
- if present, is mapped to ``og:image`` / ``twitter:image``. The exact same
- file is used without any resizing or cropping and is assumed to be in
- landscape.
+- The :rst:`:cover:` field (e.g. the one used on `landing pages`_), if
+ present, is mapped to ``og:image`` / ``twitter:image``, overriding the
+ global :py:`M_SOCIAL_IMAGE` setting. The exact same file is used without
+ any resizing or cropping and is assumed to be in landscape.
- ``twitter:card`` is set to ``summary_large_image`` if :rst:`:cover:` is
present and to ``summary`` otherwise
- ``og:type`` is set to ``page``
:cover: {filename}/static/cover.jpg
:summary: This is the brand you need.
-.. note-success::
+.. block-success:: Recommended sizes for cover images
- You can see how page links will display by pasting
- URL of the `index page <{filename}/index.rst>`_ into either
- `Facebook Debugger <https://developers.facebook.com/tools/debug/>`_ or
- `Twitter Card Validator <https://cards-dev.twitter.com/validator>`_.
+ Unlike the global site image described in `(Social) meta tags`_,
+ page-specific cover images are assumed to be larger and in landscape to
+ display large on top of the link, as they should act to promote the
+ particular content instead of being just a decoration.
+
+ `Facebook recommendations for the cover image <https://developers.facebook.com/docs/sharing/best-practices/#images>`_
+ say that the image should have 1.91:1 aspect ratio and be ideally at least
+ 1200\ |x|\ 630 px large, while `Twitter recommends <https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary-card-with-large-image>`_ 2:1 aspect ratio and at
+ most 4096\ |x|\ 4096 px. In case of Twitter, the large image display is
+ controlled explicitly by having ``twitter:card`` set to ``summary_large_image``,
+ but for Facebook one needs to rely on their autodetection. Make sure the
+ image is at least 600\ |x|\ 315 px to avoid fallback to a small thumbnail.
+
+.. note-info::
+
+ You can see how page links will display by pasting URL of the
+ `index page <{filename}/index.rst>`_ into either `Facebook Debugger`_ or
+ `Twitter Card Validator`_.
`Articles`_
===========
`(Social) meta tags for articles`_
----------------------------------
-Like with pages, you can use :rst:`:description:` field to populate
-:html:`<meta name="description">`, which can be then shown in search engine
-results. Other than that, the field doesn't appear anywhere in the rendered
-article. `Open Graph`_ and `Twitter Card`_ :html:`<meta>` tags are also
-supported in a similar way:
+Every article has :html:`<link rel="canonical">` pointing to its URL to avoid
+duplicates in search engines when using GET parameters. In addition to the
+global meta tags described in `(Social) meta tags`_ above, you can use the
+:rst:`:description:` field to populate :html:`<meta name="description">`. Other
+than that, the field doesn't appear anywhere in the rendered article. If such
+field is not set, the description :html:`<meta>` tag is not rendered at all.
+Again, it's recommended to add it to :py:`FORMATTED_FIELDS`.
+
+The global `Open Graph`_ and `Twitter Card`_ :html:`<meta>` tags are
+specialized for articles like this:
- Article title is mapped to ``og:title`` / ``twitter:title``
- Article URL is mapped to ``og:url``
summary, Pelican takes it from the first few sentences of the content and
that may not be what you want. This is also different from the
:rst:`:description:` field mentioned above.
-- The :rst:`:cover:` field from `jumbo articles <#jumbo-articles>`_, if
- present, is mapped to ``og:image`` / ``twitter:image``. The exact same
- file is used without any resizing or cropping and is assumed to be in
- landscape.
+- The :rst:`:cover:` field from `jumbo articles`_, if present, is mapped to
+ ``og:image`` / ``twitter:image``, overriding the global :py:`M_SOCIAL_IMAGE`
+ setting. The exact same file is used without any resizing or cropping and
+ is assumed to be in landscape. See `(Social) meta tags for pages`_ above
+ for image size recommendations.
- ``twitter:card`` is set to ``summary_large_image`` if :rst:`:cover:` is
present and to ``summary`` otherwise
- ``og:type`` is set to ``article``
-.. note-success::
+.. note-info::
You can see how article links will display by pasting
URL of e.g. the `jumbo article`_ into either `Facebook Debugger`_ or
{% endif %}
{% endblock %}
+{% block meta %}
+ {% if M_BLOG_DESCRIPTION %}
+ <meta name="description" content="{{ M_BLOG_DESCRIPTION|e }}" />
+ {% endif %}
+{% endblock %}
+
{% block social %}
{{- super() -}}
{# this has to be here otherwise the spacing is all wrong. fuck. #}
{% block social_url %}
<meta property="og:url" content="{{ M_BLOG_URL|format_siteurl|e }}" />
{% endblock %}
+ {% if M_SOCIAL_BLOG_SUMMARY %}
+ <meta property="og:description" content="{{ M_SOCIAL_BLOG_SUMMARY|e }}" />
+ <meta name="twitter:description" content="{{ M_SOCIAL_BLOG_SUMMARY|e }}" />
+ {% endif %}
+ {% if M_SOCIAL_IMAGE %}
+ <meta property="og:image" content="{{ M_SOCIAL_IMAGE|format_siteurl|e }}" />
+ <meta name="twitter:image" content="{{ M_SOCIAL_IMAGE|format_siteurl|e }}" />
+ {% endif %}
<meta name="twitter:card" content="summary" />
<meta property="og:type" content="website" />
{% endblock %}
<meta property="og:image" content="{{ article.cover|expand_link(article)|e }}" />
<meta name="twitter:image" content="{{ article.cover|expand_link(article)|e }}" />
<meta name="twitter:card" content="summary_large_image" />
- {% else %}
+ {% elif M_SOCIAL_IMAGE %}
+ <meta property="og:image" content="{{ M_SOCIAL_IMAGE|format_siteurl|e }}" />
+ <meta name="twitter:image" content="{{ M_SOCIAL_IMAGE|format_siteurl|e }}" />
+ {% endif %}
+ {% if not article.cover %}
<meta name="twitter:card" content="summary" />
{% endif %}
<meta property="og:type" content="article" />
{% endif %}
{% block meta %}
{% endblock meta %}
+ {% if M_SOCIAL_TWITTER_SITE %}
+ <meta name="twitter:site" content="{{ M_SOCIAL_TWITTER_SITE }}" />
+ {% endif %}
+ {% if M_SOCIAL_TWITTER_SITE_ID %}
+ <meta name="twitter:site:id" content="{{ M_SOCIAL_TWITTER_SITE_ID }}" />
+ {% endif %}
{% block social %}
{% endblock social %}
</head>
{{- super() -}}
{% block social_title_url %}
{% endblock social_title_url %}
+ {% if M_SOCIAL_IMAGE %}
+ <meta property="og:image" content="{{ M_SOCIAL_IMAGE|format_siteurl|e }}" />
+ <meta name="twitter:image" content="{{ M_SOCIAL_IMAGE|format_siteurl|e }}" />
+ {% endif %}
<meta name="twitter:card" content="summary" />
<meta property="og:type" content="website" />
{% endblock %}
<meta property="og:image" content="{{ page.cover|expand_link(page)|e }}" />
<meta name="twitter:image" content="{{ page.cover|expand_link(page)|e }}" />
<meta name="twitter:card" content="summary_large_image" />
- {% else %}
+ {% elif M_SOCIAL_IMAGE %}
+ <meta property="og:image" content="{{ M_SOCIAL_IMAGE|format_siteurl }}" />
+ <meta name="twitter:image" content="{{ M_SOCIAL_IMAGE|format_siteurl }}" />
+ {% endif %}
+ {% if not page.cover %}
<meta name="twitter:card" content="summary" />
{% endif %}
<meta property="og:type" content="page" />
--- /dev/null
+<!DOCTYPE html>
+<html lang="en" prefix="og: http://ogp.me/ns#">
+<head>
+ <meta charset="UTF-8" />
+ <title>An article | A Pelican 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" />
+ <link rel="canonical" href="article.html" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="twitter:site" content="@czmosra" />
+ <meta name="twitter:site:id" content="1537427036" />
+ <meta property="og:site_name" content="A Pelican Blog" />
+ <meta property="og:title" content="An article" />
+ <meta name="twitter:title" content="An article" />
+ <meta property="og:url" content="article.html" />
+ <meta property="og:image" content="http://your.brand/static/site.png" />
+ <meta name="twitter:image" content="http://your.brand/static/site.png" />
+ <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" rel="bookmark" title="Permalink to An article">
+ <time class="m-date" datetime="2017-12-16T00:00:00+00:00">
+ Dec <span class="m-date-day">16</span> 2017
+ </time>
+ An article
+ </a></h1>
+ </header>
+ <div class="m-clearfix-l"></div>
+ <footer>
+ <p>Posted by <a href="author-the-author.html">The Author</a> on <time datetime="2017-12-16T00:00:00+00:00">Dec 16, 2017</time> in <a href="category-a-category.html">A category</a>. Tags: <a href="tag-a-tag.html">A 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-a-category.html">A category</a></li>
+ </ol>
+ <h3>Tag cloud</h3>
+ <ul class="m-tagcloud">
+ <li class="m-tag-5"><a href="tag-a-tag.html">A tag</a></li>
+ </ul>
+ </nav>
+ </div>
+</div>
+</main>
+</body>
+</html>
--- /dev/null
+An article
+##########
+
+:date: 2017-12-16
+:category: A category
+:tags: A tag
+:author: The Author
--- /dev/null
+<!DOCTYPE html>
+<html lang="en" prefix="og: http://ogp.me/ns#">
+<head>
+ <meta charset="UTF-8" />
+ <title>Posts by The Author | A Pelican 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" />
+ <meta name="twitter:site" content="@czmosra" />
+ <meta name="twitter:site:id" content="1537427036" />
+ <meta property="og:site_name" content="A Pelican Blog" />
+ <meta property="og:title" content="The Author" />
+ <meta name="twitter:title" content="The Author" />
+ <meta property="og:url" content="author-the-author.html" />
+ <meta property="og:image" content="http://your.brand/static/site.png" />
+ <meta name="twitter:image" content="http://your.brand/static/site.png" />
+ <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">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>The Author</em>. <a href="./">Show all posts.</a>
+ </div>
+ <article>
+ <header>
+ <h1><a href="article.html" rel="bookmark" title="Permalink to An article">
+ <time class="m-date" datetime="2017-12-16T00:00:00+00:00">
+ Dec <span class="m-date-day">16</span> 2017
+ </time>
+ An article
+ </a></h1>
+ </header>
+ <footer>
+ <p>Posted by <a href="author-the-author.html">The Author</a> on <time datetime="2017-12-16T00:00:00+00:00">Dec 16, 2017</time> in <a href="category-a-category.html">A category</a>. Tags: <a href="tag-a-tag.html">A tag</a>.</p>
+ </footer>
+ <div class="m-clearfix-l"></div>
+ </article>
+ </div>
+ <nav class="m-navpanel m-col-m-2">
+ <h3>Categories</h3>
+ <ol class="m-block-bar-m">
+ <li><a href="category-a-category.html">A category</a></li>
+ </ol>
+ <h3>Tag cloud</h3>
+ <ul class="m-tagcloud">
+ <li class="m-tag-5"><a href="tag-a-tag.html">A tag</a></li>
+ </ul>
+ </nav>
+ </div>
+</div>
+</main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en" prefix="og: http://ogp.me/ns#">
+<head>
+ <meta charset="UTF-8" />
+ <title>A category | A Pelican 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" />
+ <meta name="twitter:site" content="@czmosra" />
+ <meta name="twitter:site:id" content="1537427036" />
+ <meta property="og:site_name" content="A Pelican Blog" />
+ <meta property="og:title" content="A category" />
+ <meta name="twitter:title" content="A category" />
+ <meta property="og:url" content="category-a-category.html" />
+ <meta property="og:image" content="http://your.brand/static/site.png" />
+ <meta name="twitter:image" content="http://your.brand/static/site.png" />
+ <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">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>A category</em>. <a href="./">Show all posts.</a>
+ </div>
+ <article>
+ <header>
+ <h1><a href="article.html" rel="bookmark" title="Permalink to An article">
+ <time class="m-date" datetime="2017-12-16T00:00:00+00:00">
+ Dec <span class="m-date-day">16</span> 2017
+ </time>
+ An article
+ </a></h1>
+ </header>
+ <footer>
+ <p>Posted by <a href="author-the-author.html">The Author</a> on <time datetime="2017-12-16T00:00:00+00:00">Dec 16, 2017</time> in <a href="category-a-category.html">A category</a>. Tags: <a href="tag-a-tag.html">A tag</a>.</p>
+ </footer>
+ <div class="m-clearfix-l"></div>
+ </article>
+ </div>
+ <nav class="m-navpanel m-col-m-2">
+ <h3>Categories</h3>
+ <ol class="m-block-bar-m">
+ <li><a href="category-a-category.html">A category</a></li>
+ </ol>
+ <h3>Tag cloud</h3>
+ <ul class="m-tagcloud">
+ <li class="m-tag-5"><a href="tag-a-tag.html">A tag</a></li>
+ </ul>
+ </nav>
+ </div>
+</div>
+</main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en" prefix="og: http://ogp.me/ns#">
+<head>
+ <meta charset="UTF-8" />
+ <title>Posts tagged A tag | A Pelican 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" />
+ <meta name="twitter:site" content="@czmosra" />
+ <meta name="twitter:site:id" content="1537427036" />
+ <meta property="og:site_name" content="A Pelican Blog" />
+ <meta property="og:title" content="A tag" />
+ <meta name="twitter:title" content="A tag" />
+ <meta property="og:url" content="tag-a-tag.html" />
+ <meta property="og:image" content="http://your.brand/static/site.png" />
+ <meta name="twitter:image" content="http://your.brand/static/site.png" />
+ <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">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>A tag</em>. <a href="./">Show all posts.</a>
+ </div>
+ <article>
+ <header>
+ <h1><a href="article.html" rel="bookmark" title="Permalink to An article">
+ <time class="m-date" datetime="2017-12-16T00:00:00+00:00">
+ Dec <span class="m-date-day">16</span> 2017
+ </time>
+ An article
+ </a></h1>
+ </header>
+ <footer>
+ <p>Posted by <a href="author-the-author.html">The Author</a> on <time datetime="2017-12-16T00:00:00+00:00">Dec 16, 2017</time> in <a href="category-a-category.html">A category</a>. Tags: <a href="tag-a-tag.html">A tag</a>.</p>
+ </footer>
+ <div class="m-clearfix-l"></div>
+ </article>
+ </div>
+ <nav class="m-navpanel m-col-m-2">
+ <h3>Categories</h3>
+ <ol class="m-block-bar-m">
+ <li><a href="category-a-category.html">A category</a></li>
+ </ol>
+ <h3>Tag cloud</h3>
+ <ul class="m-tagcloud">
+ <li class="m-tag-5"><a href="tag-a-tag.html">A tag</a></li>
+ </ul>
+ </nav>
+ </div>
+</div>
+</main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en" prefix="og: http://ogp.me/ns#">
+<head>
+ <meta charset="UTF-8" />
+ <title>Your Brand 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="http://your.brand/static/m-dark.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="description" content="Your Brand provides everything you'll ever need." />
+ <meta name="twitter:site" content="@czmosra" />
+ <meta name="twitter:site:id" content="1537427036" />
+ <meta property="og:site_name" content="Your Brand Blog" />
+ <meta property="og:title" content="Your Brand Blog" />
+ <meta name="twitter:title" content="Your Brand Blog" />
+ <meta property="og:url" content="http://blog.your.brand/" />
+ <meta property="og:description" content="This is The Brand." />
+ <meta name="twitter:description" content="This is The Brand." />
+ <meta property="og:image" content="http://your.brand/static/site.png" />
+ <meta name="twitter:image" content="http://your.brand/static/site.png" />
+ <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">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-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-l-10 m-push-l-1">
+ <p>A Pelican Blog. Powered by <a href="https://getpelican.com">Pelican</a> and <a href="http://mcss.mosra.cz">m.css</a>.</p>
+ </div>
+ </div>
+ </div>
+</nav></footer>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en" prefix="og: http://ogp.me/ns#">
+<head>
+ <meta charset="UTF-8" />
+ <title>Your Brand 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="http://your.brand/static/m-dark.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="description" content="Your Brand provides everything you'll ever need." />
+ <meta name="twitter:site" content="@czmosra" />
+ <meta name="twitter:site:id" content="1537427036" />
+ <meta property="og:site_name" content="Your Brand Blog" />
+ <meta property="og:title" content="Your Brand Blog" />
+ <meta name="twitter:title" content="Your Brand Blog" />
+ <meta property="og:url" content="http://your.brand/" />
+ <meta property="og:description" content="This is The Brand." />
+ <meta name="twitter:description" content="This is The Brand." />
+ <meta property="og:image" content="http://your.brand/static/site.png" />
+ <meta name="twitter:image" content="http://your.brand/static/site.png" />
+ <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">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-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-l-10 m-push-l-1">
+ <p>A Pelican Blog. Powered by <a href="https://getpelican.com">Pelican</a> and <a href="http://mcss.mosra.cz">m.css</a>.</p>
+ </div>
+ </div>
+ </div>
+</nav></footer>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en" prefix="og: http://ogp.me/ns#">
+<head>
+ <meta charset="UTF-8" />
+ <title>A page | A Pelican 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" />
+ <link rel="canonical" href="page.html" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="twitter:site" content="@czmosra" />
+ <meta name="twitter:site:id" content="1537427036" />
+ <meta property="og:site_name" content="A Pelican Blog" />
+ <meta property="og:title" content="A page" />
+ <meta name="twitter:title" content="A page" />
+ <meta property="og:url" content="page.html" />
+ <meta property="og:image" content="http://your.brand/static/site.png" />
+ <meta name="twitter:image" content="http://your.brand/static/site.png" />
+ <meta name="twitter:card" content="summary" />
+ <meta property="og:type" content="page" />
+</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>
+<article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>A page</h1>
+ </div>
+ </div>
+ </div>
+</article>
+</main>
+</body>
+</html>
--- /dev/null
+A page
+######
self.assertEqual(*self.actual_expected_contents('article.html'))
self.assertEqual(*self.actual_expected_contents('article-jumbo.html'))
+
+class GlobalSocialMeta(BlogTestCase):
+ def __init__(self, *args, **kwargs):
+ super().__init__(__file__, 'global_social_meta', *args, **kwargs)
+
+ def test(self):
+ self.run_pelican({
+ 'M_BLOG_DESCRIPTION': 'This is not displayed anywhere.',
+ 'M_SOCIAL_TWITTER_SITE': '@czmosra',
+ 'M_SOCIAL_TWITTER_SITE_ID': '1537427036',
+ 'M_SOCIAL_IMAGE': 'http://your.brand/static/site.png',
+ 'M_SOCIAL_BLOG_SUMMARY': 'This is also not displayed anywhere.'
+ })
+
+ # Verify that the social meta tags are present in all pages
+ self.assertEqual(*self.actual_expected_contents('article.html'))
+ self.assertEqual(*self.actual_expected_contents('category-a-category.html'))
+ self.assertEqual(*self.actual_expected_contents('author-the-author.html'))
+ self.assertEqual(*self.actual_expected_contents('tag-a-tag.html'))
# 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'))
+
+class GlobalSocialMeta(BaseTestCase):
+ def __init__(self, *args, **kwargs):
+ super().__init__(__file__, 'global_social_meta', *args, **kwargs)
+
+ def test(self):
+ self.run_pelican({
+ 'SITEURL': 'http://your.brand',
+ 'M_BLOG_NAME': 'Your Brand Blog',
+ 'M_BLOG_URL': 'http://blog.your.brand/',
+ 'M_BLOG_DESCRIPTION': 'Your Brand provides everything you\'ll ever need.',
+ 'M_SOCIAL_TWITTER_SITE': '@czmosra',
+ 'M_SOCIAL_TWITTER_SITE_ID': '1537427036',
+ 'M_SOCIAL_IMAGE': 'http://your.brand/static/site.png',
+ 'M_SOCIAL_BLOG_SUMMARY': 'This is The Brand.'
+ })
+
+ # Verify that the social meta tags are present. Archives should have a
+ # different og:url but nothing else.
+ self.assertEqual(*self.actual_expected_contents('index.html'))
+ self.assertEqual(*self.actual_expected_contents('archives.html'))
# Verify that also the Pelican-produced content has correctly escaped
# everything.
self.assertEqual(*self.actual_expected_contents('content.html'))
+
+class GlobalSocialMeta(PageTestCase):
+ def __init__(self, *args, **kwargs):
+ super().__init__(__file__, 'global_social_meta', *args, **kwargs)
+
+ def test(self):
+ self.run_pelican({
+ 'M_BLOG_DESCRIPTION': 'This is not displayed anywhere.',
+ 'M_SOCIAL_TWITTER_SITE': '@czmosra',
+ 'M_SOCIAL_TWITTER_SITE_ID': '1537427036',
+ 'M_SOCIAL_IMAGE': 'http://your.brand/static/site.png',
+ 'M_SOCIAL_BLOG_SUMMARY': 'This is also not displayed anywhere.'
+ })
+
+ # Verify that the social meta tags are present
+ self.assertEqual(*self.actual_expected_contents('page.html'))