Skip to content

Commit

Permalink
Added custom Sphinx extension for OpenGraph data (#39)
Browse files Browse the repository at this point in the history
* Added custom Sphinx extension for OpenGraph data

* Updated with """
  • Loading branch information
tcmetzger committed Jul 6, 2020
1 parent 9ffe63e commit 929b833
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 11 deletions.
106 changes: 106 additions & 0 deletions docs/_ext/ogtag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
"""Automatically generates Open Graph tags for Sphinx html docs.
Based on https://sphinx-users.jp/cookbook/ogp/index.html
"""

from docutils import nodes
from sphinx import addnodes
from urllib.parse import urljoin


class Visitor:
def __init__(self, document):
self.document = document
self.text_list = []
self.images = []
self.n_sections = 0

def dispatch_visit(self, node):
# Skip toctree
if isinstance(node, addnodes.compact_paragraph) and node.get("toctree"):
raise nodes.SkipChildren

# Collect images
if isinstance(node, nodes.image):
self.images.append(node)

# Collect text (first three sections)
if self.n_sections < 3:

# Collect paragraphs
if isinstance(node, nodes.paragraph):
self.text_list.append(node.astext().replace("\n", " "))

# Include only paragraphs
if isinstance(node, nodes.section):
self.n_sections += 1

def dispatch_departure(self, node):
pass

def get_og_description(self):
# TODO: Find optimal length for description text
text = " ".join(self.text_list)
if len(text) > 200:
text = text[:197] + "..."
return text

def get_og_image_url(self, page_url):
# TODO: Check if picking first image makes sense
# TODO: Return fallback image if no image found on page
if self.images:
return urljoin(page_url, self.images[0]["uri"])
else:
return None


def get_og_tags(context, doctree, config):
# page_url
site_url = config.og_site_url
page_url = urljoin(site_url, context["pagename"] + context["file_suffix"])

# collection
visitor = Visitor(doctree)
doctree.walkabout(visitor)

# og:description
og_desc = visitor.get_og_description()

# og:image
og_image = visitor.get_og_image_url(page_url)

# OGP
tags = """
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="{cfg[og_twitter_site]}" />
<meta property="og:site_name" content="{ctx[shorttitle]}">
<meta property="og:title" content="{ctx[title]}">
<meta property="og:description" content="{desc}">
<meta property='og:url' content="{page_url}">
""".format(
ctx=context, desc=og_desc, page_url=page_url, cfg=config
)
# Add image if present, use default image if no image is found
if og_image:
tags += f'<meta property="og:image" content="{og_image}">'
elif config.og_fallback_image:
tags += f'<meta property="og:image" content="{config.og_fallback_image}">'
return tags


def html_page_context(app, pagename, templatename, context, doctree):
if not doctree:
return

context["metatags"] += get_og_tags(context, doctree, app.config)


def setup(app):
app.add_config_value("og_site_url", None, "html")
app.add_config_value("og_twitter_site", None, "html")
app.add_config_value("og_fallback_image", None, "html")
app.connect("html-page-context", html_page_context)
return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
32 changes: 21 additions & 11 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# -*- coding: utf-8 -*-
#
# complexity documentation build configuration file, created by
# sphinx-quickstart on Tue Jul 9 22:26:36 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

"""Complexity documentation build configuration file, created by
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
This file is execfile()d with the current directory set to its containing dir.
Note that not all possible configuration values are present in this
autogenerated file.
All configuration values have a default; values that are commented out
serve to show the default.
"""

import os
import sys
Expand All @@ -23,6 +24,9 @@
parent = os.path.dirname(cwd)
sys.path.insert(0, parent)

# Add path for _ext/ogtag.py extension
sys.path.append(os.path.abspath("_ext"))

import pyzillow # noqa

# -- General configuration -----------------------------------------------------
Expand All @@ -35,6 +39,7 @@
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.viewcode",
"ogtag",
# "sphinx.ext.autosummary"
]
# autosummary_generate = True
Expand Down Expand Up @@ -104,6 +109,11 @@

# -- Options for HTML output ---------------------------------------------------

# Constants for _ext/ogtag.py extension
og_site_url = "https://pyzillow.readthedocs.io/en/latest/"
og_twitter_site = "@tcmetzger"
og_fallback_image = "https://www.tcmetzger.de/STATIC/pyzillow_default.png"

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "sphinx_rtd_theme"
Expand Down

0 comments on commit 929b833

Please sign in to comment.